Использование ассоциативного массива в качестве ввода функции php

Иногда я буду писать функцию PHP с одним входом, ассоциативным массивом, содержащим все эти входы функции. Это имеет такие преимущества, как отсутствие необходимости запоминать правильный порядок ввода, но я также заметил, что он значительно облегчает реализацию изменений в больших кодовых базах; когда мне нужно добавить другую переменную, и эта переменная должна пройти через 4 или 5 ранее существовавших функций, это намного проще, когда я могу просто вставить ее в массив и передать ее.

Мой вопрос в том, есть ли недостаток в этом?

Я редко вижу функции, написанные таким образом в примерах, или в open source, которые я использую, что заставляет меня думать, что, вероятно, есть недостаток. Если нет причины не делать этого, то почему бы не написать все функции таким образом?

UPDATE

Спасибо за все ваши ответы. Похоже, выделяются две основные проблемы:

Чтение кода - невозможно определить, какие переменные входят в функцию и для чего они предназначены для

Переменная ползучесть. Может завершиться массивными массивами, отскакивающими от одной функции до следующей; нельзя передавать параметры для функций, которые их не требуют.

Каковы оба замечательных момента, о которых я не думал.

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

Ответ 1

Почему бы не написать все функции таким образом?

В этом отношении, почему бы не забыть о параметрах полностью и использовать глобальные переменные для всего? (Шучу)

Передача ассоциативного массива имеет одно полезное преимущество: вы можете сделать несколько необязательных параметров функции, и вы можете передать значение для параметра Nth без необходимости передавать значение для параметра * N-1 *.

Но у вас нет способа сделать обязательные параметры с ошибкой времени компиляции, если вы их не передадите. Вы также не можете декларировать проверку типов.

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

Альтернативой, которую я использовал, является объявление обычных параметров для тех, которые являются обязательными, а затем в качестве последнего (необязательного) аргумента объявляет ассоциативный массив с именем $options, который содержит только дополнительные элементы.

function database_connect($dbname, $user, $password, array $options = array())

Ответ 2

Недостатком является то, что любой, кто смотрит на ваш код (кроме вас), понятия не имел, какие параметры входят в метод, откуда они пришли или для чего они нужны. Они также не имеют понятия, как вызвать метод, так как это не ясно, не глядя на код, что именно требуется в этом "массиве параметров".

Ответ 3

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

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

Вы никогда не должны передавать параметры функциям, которые на самом деле не требуются им.

Ответ 4

Это не обязательно так плохо от идеи, поскольку PHP не имеет функции "аргументы ключевых слов", которая присутствует во многих других современных языках программирования (Python, Ruby и т.д.). Тем не менее, есть определенные проблемы с этим:

  • Если вы измените параметры, которые принимает функция, то, скорее всего, вам придется изменить какой-либо код, где он вызвал, в соответствии с новыми параметрами.

  • Если вы широко используете эти массивы, а во многих вызовах функций принимаете массив и просто "передаете его", это может быть признаком того, что вы должны подумать о том, чтобы превратить некоторые из этих параметров в структурированный класс.

  • Если вы используете эти массивы как изменяемую структуру данных, вы не обязательно знаете, что массив, который вы получили после вызова функции, совпадает с тем, который вы передали. Это, вероятно, вернется к вы в какой-то момент.

Ответ 5

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

Ответ 6

Если бы я взял вашу функцию и увидел, что она просто начинает ссылаться на хеш-значения внутри одного аргумента функции, я бы немного смутился. Явное указание переменных и предоставление документации в док-блоке с помощью @param чрезвычайно помогает. Необходимость добавления аргумента в двух местах - это небольшая стоимость по сравнению с выводами, отображаемыми в списках читаемости.

Ответ 7

Я лично использую следующий метод:

  • объявить параметр как массив в определении функции;

  • установить значение "default values". Массив;

  • совпадение переданных параметров с дефолтом в окончательный параметр assoc.array, который я использую внутри функции. Для этой цели я использую функцию param_default().

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

// default values fx.
function param_default( $def = array(), $parameters= array() ){
    $parm_diff = array();
    $ak=array();
    $va=array();
    $parm = array();
    foreach($def as $key=>$values) if(!in_array($key, array_keys($parameters))){
        $ak[]=$key;
        $va[]=$values;
    }
    $parm_diff = array_combine($ak,$va);
    $parm = array_merge($parm_diff,$parameters);
    unset($parm_diff, $ak,$va);

    return $parm;
}

Итак, это простой пример использования:

<?php
// sample use 
 function my_func( $parameters = array() ){
    $def = array(
        'first' => 1,
        'second' => 'foo',
        'third' => -1
     );
   $parm = param_default( $def, $parameters );
   //hereon I can use my array

   var_dump($param);

   if ($param['second'] !=='foo'){
       echo 'Not foo!!';
       // whatever...
   }

   return true;
}
?>

Пример вывода:

 // calling my_fun()

$example = my_func( array('second'=>'bar') );

// results in 
$param array: 
'first' => 1,
'second' => 'bar',
'third' => -1

Ответ 8

Самый большой запах кода заключается в том, что добавление другой переменной будет каскадом через 4-5 различных функций. Я не могу думать о причине, которая должна произойти.

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

Ответ 9

Это значительно облегчает сбор документации, если у вас есть параметры, названные и переданные отдельно. Вы можете подумать, что использование массива упрощает добавление нового кода, но его потенциал не улучшает читаемость. Плюс уходите от своего кода на 2 месяца и возвращайтесь... выясняя, в каком порядке добавить параметры в ваш массив, в ситуациях которого станет массивная головная боль.

Ответ 10

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

В общем случае, если ваши функции имеют > 3 аргумента, это все равно станет нечитаемым.

В качестве альтернативы и часто используемый шаблон делает единственный аргумент вашей функции объектом (classed-). "Класс параметров" точно определит, что поддерживается.

Ответ 12

, если ваш вопрос заключается в том, как передать массив в качестве функции ввода, это ваш ответ:

<?php
 function city($input){
   $i=count($input['iran']);
   $result="";
     for($b=1;$b<=$i;$b++){
       $result.='<div style="background:gold">'.$input['iran'][$b].'</div>';
       }
      return $result;
    }
$cityName['iran'][1]="Tehran";
$cityName['iran'][2]="Qom";
$cityName['iran'][3]="MashHad";
$cityName['iran'][4]="Isfahan";
$cityName['iran'][5]="Shiraz";
$cityName['iran'][6]="Yazd";

echo city($cityName);
?>

Ответ 13

Создайте функцию:

function testing($argumentos) {
    $var_1 = $argumentos['var_01'];
    $var_2 = $argumentos['var_02'];

    echo $var_1 . " " . $var_2;
} 

Вызвать функцию:

testing(array('var_01' => "mierda", 'var_02' => "conio!"));

Вывод:

 mierda conio!