Возможно ли в PHP 4/5 указать именованный необязательный параметр при вызове, пропуская те, которые вы не хотите указывать (например, в python)?
Что-то вроде:
function foo($a,$b='', $c='') { // whatever } foo("hello", $c="bar"); // we want $b as the default, but specify $c
благодаря
Нет, это невозможно: если вы хотите передать третий параметр, вам нужно передать второй. Именованные параметры также невозможны.
«Решение» – это использовать только один параметр, массив и всегда передавать его … Но не всегда все это определяет.
Например :
function foo($params) { var_dump($params); }
И называя это так:
foo(array( 'a' => 'hello', )); foo(array( 'a' => 'hello', 'c' => 'glop', )); foo(array( 'a' => 'hello', 'test' => 'another one', ));
Вы получите этот результат:
array 'a' => string 'hello' (length=5) array 'a' => string 'hello' (length=5) 'c' => string 'glop' (length=4) array 'a' => string 'hello' (length=5) 'test' => string 'another one' (length=11)
Но мне не очень нравится это решение:
Поэтому я бы пошел с этим только в очень конкретных случаях – для функций с большим количеством опциональных параметров, например …
Нет, PHP не может передавать аргументы по имени.
Если у вас есть функция, которая принимает много аргументов, и все они имеют значения по умолчанию, вы можете подумать о том, чтобы заставить функцию принимать массив аргументов:
function test (array $args) { $defaults = array('a' => '', 'b' => '', 'c' => ''); $args = array_merge($defaults, array_intersect_key($args, $defaults)); list($a, $b, $c) = array_values($args); // an alternative to list(): extract($args); // you can now use $a, $b, $c }
Смотрите в действии .
Нет, это не так.
Единственный способ, которым вы можете это сделать, – это использовать массивы с именованными ключами, а что нет.
С PHP, порядок аргументов имеет значение. Вы не можете указать конкретный аргумент неуместно, но вместо этого вы можете пропустить аргументы, передав NULL, если вы не возражаете, чтобы значение в вашей функции имело значение NULL.
foo("hello", NULL, "bar");
Начиная с PHP 5.4 у вас есть синтаксис коротких массивов (не обязательно указывать массивы с громоздким «массивом» и вместо этого использовать «[]»).
Вы можете имитировать именованные параметры разными способами: один хороший и простой способ:
bar('one', ['a1' => 'two', 'bar' => 'three', 'foo' => 'four']); // output: twothreefour function bar ($a1, $kwargs = ['bar' => null, 'foo' => null]) { extract($kwargs); echo $a1; echo $bar; echo $foo; }
Это не совсем красиво, но это трюк, некоторые могут сказать.
class NamedArguments { static function init($args) { $assoc = reset($args); if (is_array($assoc)) { $diff = array_diff(array_keys($assoc), array_keys($args)); if (empty($diff)) return $assoc; trigger_error('Invalid parameters: '.join(',',$diff), E_USER_ERROR); } return array(); } } class Test { public static function foobar($required, $optional1 = '', $optional2 = '') { extract(NamedArguments::init(get_defined_vars())); printf("required: %s, optional1: %s, optional2: %s\n", $required, $optional1, $optional2); } } Test::foobar("required", "optional1", "optional2"); Test::foobar(array( 'required' => 'required', 'optional1' => 'optional1', 'optional2' => 'optional2' ));
Вы можете сохранить phpdoc и возможность устанавливать значения по умолчанию, передавая объект вместо массива, например
class FooOptions { $opt1 = 'x'; $opt2 = 'y'; /* etc */ };
Это также позволяет выполнять строгую проверку типов в вызове функции, если вы хотите:
function foo (FooOptions $opts) { ... }
Разумеется, вы можете заплатить за это, добавив дополнительную детализацию объекта FooOptions. К сожалению, нет абсолютно бесплатной езды.
Обычно вы не можете, но я думаю, что есть много способов передать именованные аргументы функции PHP. Лично я ретранслирую по определению с использованием массивов и просто вызываю то, что мне нужно передать:
class Test{ public $a = false; private $b = false; public $c = false; public $d = false; public $e = false; public function _factory(){ $args = func_get_args(); $args = $args[0]; $this->a = array_key_exists("a",$args) ? $args["a"] : 0; $this->b = array_key_exists("b",$args) ? $args["b"] : 0; $this->c = array_key_exists("c",$args) ? $args["c"] : 0; $this->d = array_key_exists("d",$args) ? $args["d"] : 0; $this->e = array_key_exists("e",$args) ? $args["e"] : 0; } public function show(){ var_dump($this); } } $test = new Test(); $args["c"]=999; $test->_factory($args); $test->show();
Здесь приведен пример: http://sandbox.onlinephpfunctions.com/code/d7f27c6e504737482d396cbd6cdf1cc118e8c1ff
Если мне нужно передать 10 аргументов, и 3 из них – это данные, которые мне действительно нужны, НЕ ДАЖЕ SMART, чтобы перейти в функцию что-то вроде
return myfunction(false,false,10,false,false,"date",false,false,false,"desc");
При подходе, который я даю, вы можете настроить любой из 10 аргументов в массив:
$arr['count']=10; $arr['type']="date"; $arr['order']="desc"; return myfunction($arr);
У меня есть сообщение в моем блоге, объясняющее этот процесс более подробно.
http://www.tbogard.com/2013/03/07/passing-named-arguments-to-a-function-in-php
Вот что я использовал. Определение функции принимает один необязательный аргумент массива, который указывает необязательные именованные аргументы:
function func($arg, $options = Array()) { $defaults = Array('foo' => 1.0, 'bar' => FALSE); $options = array_merge($default, $options); // Normal function body here. Use $options['foo'] and // $options['bar'] to fetch named parameter values. ... }
Обычно вы можете вызывать без каких-либо именованных аргументов:
func("xyzzy")
Чтобы указать необязательный именованный аргумент, передайте его в необязательном массиве:
func("xyzzy", Array('foo' => 5.7))
Нет, не совсем. Есть несколько альтернатив, которые вы могли бы использовать.
test(null,null,"hello")
Или передайте массив:
test(array('c' => "hello"));
Тогда функция может быть:
function test($array) { $c = isset($array[c]) ? $array[c] : ''; }
Или добавьте функцию между ними, но я бы не предложил этого:
function ctest($c) { test('','',$c); }
Попробуйте function test ($a="",$b="",&$c=""){}
Помещение &
до $c
Я так не думаю … Если вам нужно вызвать, например, функцию substr , которая имеет 3 параметра, и вы хотите установить $ length без установки $ start, вы будете вынуждены это сделать.
substr($str,0,10);
хороший способ переопределить это – всегда использовать массивы для параметров
Простой ответ. Нет, вы не можете.
Вы можете попробовать обойти его, передав объект / массив или используя другие шаблоны инъекций зависимостей.
Кроме того, попробуйте использовать нули, а не пустые строки, поскольку более определенно проверить их существование, используя is_null ()
например:
function test ($a=null,$b=null,$c=null){ if (is_null($a) { //do something about $a } if (is_null($b) { //do something about $b } if (is_null($c) { //do something about $c } }
для этого:
test(null,null,"Hello");
В очень короткие, иногда да, используя отраженные и типизированные переменные. Однако я думаю, что это, вероятно, не то, что вам нужно.
Лучшее решение вашей проблемы, вероятно, должно пройти в 3 аргументах, поскольку функции обрабатывают недостающий внутри вашей функции самостоятельно
<?php function test(array $params) { //Check for nulls etc etc $a = $params['a']; $b = $params['b']; ...etc etc }
Вы не можете сделать это на python. Anway, вы можете передать ассоциативный массив и использовать записи массива по их имени:
function test ($args=array('a'=>'','b'=>'','c'=>'')) { // do something } test(array('c'=>'Hello'));
Это не уменьшает типизацию, но, по крайней мере, более описательно, имея имена аргументов, видимые и читаемые в вызове.
Вот работа:
function set_param_defaults($params) { foreach($params['default_values'] as $arg_name => $arg_value) { if (!isset($params[$arg_name])) { $params[$arg_name] = $arg_value; } } return $params; } function foo($z, $x = null, $y = null) { $default_values = ['x' => 'default value for x', 'y' => 'default value for y']; $params = set_param_defaults(get_defined_vars()); print "$z\n"; print $params['x'] . "\n"; print $params['y'] . "\n"; } foo('set z value', null, 'set y value'); print "\n"; foo('set z value', 'set x value');
ALTERNATIVELY: Лично я бы пошел с этим методом.
function foo($z, $x_y) { $x_y += ['x' => 'default value for x', 'y' => 'default value for y']; print "$z\n"; print $x_y['x'] . "\n"; print $x_y['y'] . "\n"; } foo('set z value', ['y' => 'set y value']); print "\n"; foo('set z value', ['x' => 'set x value']);
Распечатывайте выходы для обоих примеров.
1-й вызов:
2-й вызов:
Просто используйте шаблон ассоциативного массива Drupal. Для необязательных аргументов по умолчанию просто примите аргумент $options
который является ассоциативным массивом. Затем используйте оператор array +
для установки любых отсутствующих ключей в массиве.
function foo ($a_required_parameter, $options = array()) { $options += array( 'b' => '', 'c' => '', ); // whatever } foo('a', array('c' => 'c's value')); // No need to pass b when specifying c.