Считаете ли вы foreach ((array) $ foo as $ bar) запахом кода?

Считаете ли вы это запахом кода?

foreach((array)$foo as $bar)
{
    $bar->doStuff();
}

Должен ли я использовать это вместо этого?

if (isset($foo) && is_array($foo))
{
    foreach($foo as $bar)
    {
        $bar->doStuff();
    }
}

Какие-либо другие хорошие практики для покрытия неустановленных переменных и утверждения массива?

В качестве примечания ... Я действительно ненавижу фразу "запах кода". Я думаю, что на SO есть даже пост об этом!

BobbyShaftoe 07.01.2009 11:52

Как бы вы тогда сформулировали мой вопрос? :)

Karsten 07.01.2009 12:07

@Bobby: Будьте предельно честными, никого не волнует, что вам не нравится. Кодовый запах - это устоявшаяся фраза, которую все знают и понимают. Это эффективное общение, которое следует ценить.

Ollie Saunders 04.09.2010 16:44
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
2
3
755
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Лично я бы никогда не применил первый метод и всегда выбрал второй.

Если вы проверяете, установлены ли переменные, вы можете их инициализировать:

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.

cletus 07.01.2009 14:02

Если function_returning_an_array() возвращает пустой массив (что, на мой взгляд, вполне возможно), ветвь if ($foo) не будет оцениваться.

Ionuț G. Stan 03.08.2009 16:02
@lonut G. Stan: Если есть действие, которое необходимо выполнить, даже когда массив пуст, вы все равно можете использовать вместо него if ($foo !== false).
too much php 04.08.2009 03:17

Если $ 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 - это язык утиный, который имеет как преимущества, так и недостатки, но это одно из преимуществ, так что наслаждайтесь им!

Другие вопросы по теме