Использование ассоциативного массива в качестве входа в функцию php - PullRequest
12 голосов
/ 15 июня 2009

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

У меня вопрос, есть ли у этого недостаток?

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

UPDATE

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

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

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

Обе великие вещи, о которых я не задумывался.

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

Ответы [ 13 ]

12 голосов
/ 15 июня 2009

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

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

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

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

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

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

function database_connect($dbname, $user, $password, array $options = array())
9 голосов
/ 15 июня 2009

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

2 голосов
/ 15 июня 2009

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

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

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

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

2 голосов
/ 15 июня 2009

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

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

Никогда не передавайте параметры функциям, которые им на самом деле не нужны.

1 голос
/ 29 сентября 2015

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

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

  2. устанавливает ассоциацию "значения по умолчанию". массив;

  3. соответствует переданным параметрам по умолчанию в определенном параметре 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
1 голос
/ 15 июня 2009

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

1 голос
/ 15 июня 2009

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

0 голосов
/ 25 февраля 2016

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

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!
0 голосов
/ 10 мая 2014

если ваша очередь состоит в том, чтобы дать массив в качестве функции ввода, это ваш ответ:

<?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);
?>
0 голосов
/ 25 июля 2011

Если кто-то все еще ищет решение - вот оно (пример-функция: __ construct () ):

Извлеките параметры $ _GET / $ _ POST и передайте их конструктору

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...