Любой способ указать дополнительные значения параметра в PHP?

Предположим, у меня есть функция PHP foo:

function foo($firstName = 'john', $lastName = 'doe') { echo $firstName . " " . $lastName; } // foo(); --> john doe 

Есть ли способ указать только второй необязательный параметр?

Пример:

 foo($lastName='smith'); // output: john smith 

Solutions Collecting From Web of "Любой способ указать дополнительные значения параметра в PHP?"

PHP не поддерживает именованные параметры для самих функций. Однако есть некоторые способы обойти это:

  1. Используйте массив как единственный аргумент для функции. Затем вы можете вывести значения из массива. Это позволяет использовать именованные аргументы в массиве.
  2. Если вы хотите разрешить дополнительное число аргументов в зависимости от контекста, вы можете использовать func_num_args и func_get_args, а не указывать действительные параметры в определении функции. Затем, основываясь на количестве аргументов, строковых длинах и т. Д., Вы можете определить, что делать.
  3. Передайте нулевое значение любому аргументу, который вы не хотите указывать. Не очень обойти это, но это работает.
  4. Если вы работаете в объектном контексте, вы можете использовать магический метод __call () для обработки этих типов запросов, чтобы вы могли направлять частные методы на основе того, какие аргументы были переданы.

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

 function foo($arguments) { $defaults = array( 'firstName' => 'john', 'lastName' => 'doe', ); $arguments = array_merge($defaults, $arguments); echo $arguments['firstName'] . ' ' . $arguments['lastName']; } 

Применение:

 foo(array('lastName' => 'smith')); // output: john smith 

Вы можете реорганизовать свой код немного:

 function foo($firstName = NULL, $lastName = NULL) { if (is_null($firstName)) { $firstName = 'john'; } if (is_null($lastName )) { $lastName = 'doe'; } echo $firstName . " " . $lastName; } foo(); // john doe foo('bill'); // bill doe foo(NULL,'smith'); // john smith foo('bill','smith'); // bill smith 

Если у вас есть несколько необязательных параметров, одно решение – передать один параметр, который является хэш-массивом:

 function foo(array $params = array()) { echo $params['firstName'] . " " . $params['lastName']; } foo(array('lastName'=>'smith')); 

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

Нет. Обычный способ сделать это – с некоторой эвристикой, чтобы определить, какой параметр подразумевается, например длина строки, ввод текста и т. Д.

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

То, как вы хотите: нет.

Вы можете использовать некоторую специальную метку, например NULL, чтобы отметить, что значение не указано:

 function foo($firstName, $lastName = 'doe') { if (is_null($firstName)) $firstName = 'john'; echo $firstName . " " . $lastName; } foo(null, 'smith'); 

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

 function some_func($required_parameter, &$optional_reference_parameter = null, $options = null) { $options_default = array( 'foo' => null, ); extract($options ? array_intersect_key($options, $options_default) + $options_default : $options_default); unset($options, $options_default); //do stuff like if ($foo !== null) { bar(); } } 

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

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

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

 $func = 'foo'; $args = ['lastName' => 'Smith']; $ref = new ReflectionFunction($func); $ref->invokeArgs(array_map(function (ReflectionParameter $param) use ($args) { if (array_key_exists($param->getName(), $args)) { return $args[$param->getName()]; } if ($param->isOptional()) { return $param->getDefaultValue(); } throw new InvalidArgumentException("{$param->getName()} is not optional"); }, $ref->getParameters())); 

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

 call_func_with_args_by_name('foo', ['lastName' => 'Smith']); 

Я хочу, чтобы это решение было на SO, когда я начал использовать PHP 2,5 года назад. Он отлично работает в примерах, которые я создал, и я не понимаю, почему он не должен быть полностью расширяемым. Он предлагает следующие преимущества по сравнению с предлагаемыми ранее:

(i) доступ к параметрам внутри функции осуществляется по именованным переменным, как если бы параметры были полностью объявлены, а не требовать доступа к массиву

(ii) очень быстро и легко адаптировать существующие функции

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

метод

Определите свою функцию с ее обязательными параметрами и необязательным массивом

Объявите свои необязательные параметры как локальные переменные

Ключ: замените предварительно объявленное значение по умолчанию любых необязательных параметров, используя те, которые вы прошли через массив.

 extract(array_merge($arrDefaults, array_intersect_key($arrOptionalParams, $arrDefaults))); 

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

Например,

 function test_params($a, $b, $arrOptionalParams = array()) { $arrDefaults = array('c' => 'sat', 'd' => 'mat'); extract(array_merge($arrDefaults, array_intersect_key($arrOptionalParams, $arrDefaults))); echo "$a $b $c on the $d"; } 

и затем назовите его так

 test_params('The', 'dog', array('c' => 'stood', 'd' => 'donkey')); test_params('The', 'cat', array('d' => 'donkey')); test_params('A', 'dog', array('c' => 'stood')); 

Результаты:

Собака стояла на ослике

Кошка сидела на ослике

На коврике стояла собака

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

 function person($firstName = 'john', $lastName = 'doe') { return $firstName . " " . $lastName; } function usualFirtNamedPerson($lastName = 'doe') { return person('john', $lastName); } print(usualFirtNamedPerson('smith')); --> john smith 

Обратите внимание, что вы также можете изменить значение по умолчанию $ lastname в этом процессе, если хотите.

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

 $firstName = 'Zeno'; $lastName = 'of Elea'; print(person($firstName, $lastName)); print(person(/* $firstName = */ 'Bertrand', /* $lastName = */ 'Russel')); 

Хорошо, это не так коротко и элегантно, как person($lastName='Lennon') , но, похоже, вы не можете иметь его в PHP. И это не самый сексуальный способ закодировать его, с супер-метапрограммирующим трюком и т. Д., Но какое решение вы бы предпочли бы встретить в процессе обслуживания?

К сожалению, то, что вы пытаетесь сделать, не имеет «синтаксического сахара». Все они разные формы WTF.

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

 function foo () { $args = func_get_args(); # $args = arguments in order } 

Будет делать трюк. Старайтесь не использовать его слишком много, потому что для Php это немного на магической стороне.

Затем вы можете при желании применить значения по умолчанию и делать странные вещи на основе количества параметров.

 function foo(){ $args = func_get_args(); if( count($args) < 1 ){ return "John Smith"; } if( count($args) < 2 ) { return "John " .$args[0]; } return $args[0] . " " . $args[1]; } 

Кроме того, вы можете дополнительно эмулировать параметры стиля Perl,

 function params_collect( $arglist ){ $config = array(); for( $i = 0; $i < count($arglist); $i+=2 ){ $config[$i] = $config[$i+1]; } return $config; } function param_default( $config, $param, $default ){ if( !isset( $config[$param] ) ){ $config[$param] = $default; } return $config; } function foo(){ $args = func_get_args(); $config = params_collect( $args ); $config = param_default( $config, 'firstname' , 'John' ); $config = param_default( $config, 'lastname' , 'Smith' ); return $config['firstname'] . ' ' . $config['lastname']; } foo( 'firstname' , 'john', 'lastname' , 'bob' ); foo( 'lastname' , 'bob', 'firstname', 'bob' ); foo( 'firstname' , 'smith'); foo( 'lastname', 'john' ); 

Конечно, было бы проще использовать аргумент массива здесь, но вам разрешено иметь выбор (даже плохие способы) делать что-то.

что это лучше в Perl, потому что вы можете сделать только foo (firstname => 'john');

  • func_get_args на php.net

Нет, нет, но вы можете использовать массив:

 function foo ($nameArray) { // Work out which values are missing? echo $nameArray['firstName'] . " " . $nameArray['lastName']; } foo(array('lastName'=>'smith'));