Считаете ли вы foreach ((массив) $ foo как $ bar) запахом кода? - PullRequest
2 голосов
/ 07 января 2009

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

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

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

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

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

Ответы [ 8 ]

4 голосов
/ 07 января 2009

Они оба пахнут кодом. Второй просто уклоняется от всех сообщений об ошибках, вроде выключения пожарной сигнализации перед тем, как поджечь кухню. Оба из них говорят вам, что вы понятия не имеете, что находится в переменной $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) { ... }
2 голосов
/ 07 января 2009

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

if (! $foo or !is_array($foo))
    $foo = array();

foreach($foo as $bar)
{
    $bar->doStuff();
}
1 голос
/ 03 августа 2009

Обычно я делаю это для того, чтобы 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), что означает, что они могут использоваться в foreaches.

1 голос
/ 08 января 2009
(array)$foo != if (isset($foo) && is_array($foo))

Приведение (array) может быть полезно для приведения объектов к массивам или скалярам к массивам, чтобы вы могли создавать согласованные интерфейсы с переменными, которые могут содержать отдельные значения или массивы.

(array)$foo == array($foo)

Как определено в руководстве по PHP для типов массивов.

Так что если вам нужно всегда использовать массив, ответом будет первый фрагмент кода, который вы представили. Однако правила приведения типов по-прежнему применяются, поэтому вы можете не получить того, что хотите, поэтому обратитесь к руководству для получения дополнительной информации. В противном случае второй вариант запретил бы доступ к неустановленным переменным, которые не являются массивами.

Что касается запаха кода, я бы сказал, что проверки на неустановленные переменные, безусловно, можно избежать, однако, всегда зная, что переменная будет иметь массив, чаще, чем нет, она будет ползти вверх. Поэтому я хотел бы свести к минимуму код, заключенный в операторы is_array($foo) if-then.

1 голос
/ 07 января 2009

Если $ 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!");
}

Конечно, вам не нужно просто выходить из приложения, но делать то, что подходит в этом случае, возможно, ведение журнала или некоторую альтернативную логику.

1 голос
/ 07 января 2009

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

0 голосов
/ 16 сентября 2009

Довольно часто вы хотели бы написать функцию, которая бы принимала одно или несколько значений для параметра:

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

0 голосов
/ 16 сентября 2009
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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...