Считаете ли вы это запахом кода?
foreach((array)$foo as $bar)
{
$bar->doStuff();
}
Должен ли я использовать это вместо этого?
if (isset($foo) && is_array($foo))
{
foreach($foo as $bar)
{
$bar->doStuff();
}
}
Какие-либо другие хорошие практики для покрытия неустановленных переменных и утверждения массива?
Как бы вы тогда сформулировали мой вопрос? :)
@Bobby: Будьте предельно честными, никого не волнует, что вам не нравится. Кодовый запах - это устоявшаяся фраза, которую все знают и понимают. Это эффективное общение, которое следует ценить.






Лично я бы никогда не применил первый метод и всегда выбрал второй.
Если вы проверяете, установлены ли переменные, вы можете их инициализировать:
if (! $foo or !is_array($foo))
$foo = array();
foreach($foo as $bar)
{
$bar->doStuff();
}
Оба они запахи кода. Второй - просто уклонение от всех сообщений об ошибках, вроде выключения пожарной сигнализации перед тем, как поджечь кухню. Оба из них говорят вам, что вы понятия не имеете, что находится в переменной $foo и было ли она определена в приведенном выше коде. Вам нужно вернуться к коду и точно выяснить, что происходит с $foo.
Если бы это был мой код, $ foo, вероятно, всегда определялся бы либо как массив, либо как false, чтобы указать, что массив не нужен:
if (do_we_need_an_array())
$foo = function_returning_an_array();
else
$foo = false;
[...snip...]
if ($foo)
foreach($foo as $f) { ... }
Лично я бы предпочел пустой массив false.
Если function_returning_an_array() возвращает пустой массив (что, на мой взгляд, вполне возможно), ветвь if ($foo) не будет оцениваться.
if ($foo !== false).
Если $ foo всегда должен быть массивом, тогда вторая форма была бы намного лучше, если бы вы выполнили какую-то обработку для случая ошибки, например:
if (isset($foo) && is_array($foo))
{
foreach($foo as $bar)
{
$bar->doStuff();
}
}
else
{
// This should not happen, exit angrily.
exit("Oh crap, foo isn't an array!");
}
Конечно, вам не нужно просто выходить из приложения, но сделайте все, что уместно в этом случае, возможно, ведение журнала или какую-то альтернативную логику.
(array)$foo != if (isset($foo) && is_array($foo))
Приведение (array) может быть полезно для преобразования объектов в массивы или скаляров в массивы, чтобы вы могли создавать согласованные интерфейсы для переменных, которые могут содержать отдельные значения или массивы.
(array)$foo == array($foo)
Как определено в Руководстве по PHP для типов массивов.
Поэтому, если вам нужно всегда использовать массив, ответом будет первый представленный фрагмент кода. Однако правила приведения типов по-прежнему применяются, поэтому вы можете не получить то, что хотите, поэтому обратитесь к руководству для получения дополнительной информации. В противном случае второй вариант предотвратит доступ к неустановленным переменным, которые не являются массивами.
Что касается запаха кода, я бы сказал, что проверки на неустановленные переменные, безусловно, можно избежать, однако постоянное знание того, что переменная будет иметь массив, чаще всего будет ползать. Поэтому я бы постарался свести к минимуму код, заключенный в операторы if-then is_array($foo).
Обычно я делаю это, чтобы убедиться, что foreach может обрабатывать как скаляры, так и коллекции:
<?php
foreach (makeSureTraversable($scalarOrCollection) as $val)
{
// Do something.
}
function
makeSureTraversable($anything)
{
if (is_array($anything) || ($anything instanceof Traversable))
{
return $anything;
}
else
{
return array($anything);
}
}
Таким образом, я также обрабатываю классы, реализующие Traversable (из SPL), что означает, что их можно использовать в foreache.
if (!isset($foo) && !is_array($foo)) {
throw new InvalidArgumentException('Wrong array passed');
// Or do something to recover lost array
}
foreach($foo as $bar) {
$bar->doStuff();
}
Довольно часто вы хотели бы написать функцию, принимающую одно или несколько значений для параметра:
function getNamesById($id) { }
В этом случае было бы разумно, если бы эта функция была вызвана с массивом идентификаторов, она, вероятно, должна была бы вернуть массив имен. Точно так же, чтобы избавить вызывающий код от необходимости оборачивать ввод в массив, а затем разворачивать вывод, если вы просто передаете скаляр, то скаляр должен быть возвращен. Рассмотрим вероятное содержимое функции, предназначенной для обработки как скалярных параметров, так и параметров массива:
function getNamesById($id) {
$returnAnArray = is_array($id);
$output = array();
foreach ((array)$id as $theId) {
// perform some logic
$output[] = someFunction($theId);
}
return $returnAnArray ? $output : $output[0];
}
Вы можете видеть, что в этом случае приведение к массиву определенно упрощает задачу для всех. Как говорится, будьте либеральны в том, что вы принимаете ... Пока документировано, что это ожидал, которое может быть переменной, тогда я не вижу проблем. PHP - это язык утиный, который имеет как преимущества, так и недостатки, но это одно из преимуществ, так что наслаждайтесь им!
В качестве примечания ... Я действительно ненавижу фразу "запах кода". Я думаю, что на SO есть даже пост об этом!