Назвали необязательные аргументы PHP?
Возможно ли в PHP 4/5 указать именованный необязательный параметр при вызове, пропуская те, которые вы не хотите указывать (например, на python)?
Что-то вроде:
function foo($a,$b='', $c='') {
// whatever
}
foo("hello", $c="bar"); // we want $b as the default, but specify $c
Спасибо
Ответы
Ответ 1
Нет, это невозможно: если вы хотите передать третий параметр, вам нужно передать второй. Именованные параметры также невозможны.
"Решение" должно было бы использовать только один параметр, массив и всегда передавать его... Но не всегда все в нем.
Например:
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)
Но мне не очень нравится это решение:
- Вы потеряете phpdoc
- Ваша IDE больше не сможет дать какой-либо намек... Что плохое.
Поэтому я бы пошел с этим только в очень конкретных случаях - для функций с большим количеством опциональных параметров, например...
Ответ 2
Нет, 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
}
Посмотрите на действие.
Ответ 3
Нет, это не так.
Единственный способ сделать это - использовать массивы с именованными ключами, а что нет.
Ответ 4
С PHP, порядок аргументов имеет значение. Вы не можете указать конкретный аргумент неуместно, но вместо этого вы можете пропустить аргументы, передав NULL, если вы не возражаете, чтобы значение в вашей функции имело значение NULL.
foo("hello", NULL, "bar");
Ответ 5
Как и в 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;
}
Ответ 6
Это не совсем красиво, но это трюк, некоторые могут сказать.
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'
));
Ответ 7
Вы можете сохранить phpdoc и возможность устанавливать значения по умолчанию, передавая объект вместо массива, например.
class FooOptions {
$opt1 = 'x';
$opt2 = 'y';
/* etc */
};
Это также позволяет выполнять строгую проверку типов в вызове функции, если вы хотите:
function foo (FooOptions $opts) {
...
}
Конечно, вы можете заплатить за это с дополнительной детализацией, создающей объект FooOptions. К сожалению, нет абсолютно бесплатной езды.
Ответ 8
Обычно вы не можете, но я думаю, что существует много способов передать именованные аргументы функции 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
Ответ 9
Вот что я использовал. Определение функции принимает один необязательный аргумент массива, который указывает необязательные именованные аргументы:
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))
Ответ 10
Нет, не совсем. Есть несколько альтернатив, которые вы могли бы использовать.
test(null,null,"hello")
Или передать массив:
test(array('c' => "hello"));
Тогда функция может быть:
function test($array) {
$c = isset($array[c]) ? $array[c] : '';
}
Или добавьте функцию между ними, но я бы не предложил этого:
function ctest($c) { test('','',$c); }
Ответ 11
Попробуйте function test ($a="",$b="",&$c=""){}
Ввод &
перед $c
Ответ 12
Я так не думаю...
Если вам нужно вызвать, например, функцию substr, которая имеет 3 параметра и хочет установить $length без устанавливает $start, вы будете вынуждены это сделать.
substr($str,0,10);
хороший способ переопределить это - всегда использовать массивы для параметров
Ответ 13
Простой ответ. Нет, вы не можете.
Вы можете попробовать обойти его, передав объект/массив или используя другие шаблоны инъекций зависимостей.
Кроме того, попробуйте использовать пустые строки, а не пустые строки, поскольку более определенно проверить их существование, используя 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");
Ответ 14
В очень короткие, иногда да, используя отраженные и типизированные переменные. Однако я думаю, что это, вероятно, не то, что вам нужно.
Лучшее решение вашей проблемы, вероятно, будет передано в 3 аргументах, поскольку функции обрабатывают отсутствующий внутри вашей функции самостоятельно
<?php
function test(array $params)
{
//Check for nulls etc etc
$a = $params['a'];
$b = $params['b'];
...etc etc
}
Ответ 15
Вы не можете сделать это способом python. Anway, вы можете передать ассоциативный массив и использовать записи массива по их имени:
function test ($args=array('a'=>'','b'=>'','c'=>''))
{
// do something
}
test(array('c'=>'Hello'));
Это не уменьшает типизацию, но, по крайней мере, более описательно, имея имена аргументов, видимые и читаемые в вызове.
Ответ 16
Вот работа:
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');
АЛЬТЕРНАТИВЫ:
Лично я бы пошел с этим методом.
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-й вызов:
- установить значение z
- значение по умолчанию для x
- установить значение y
Второй вызов:
- установить значение z
- установить значение x
- значение по умолчанию для y
Ответ 17
Просто используйте шаблон ассоциативного массива Drupal. Для необязательных аргументов по умолчанию просто примите аргумент $options
, который является ассоциативным массивом. Затем используйте массив +
для установки всех отсутствующих ключей в массиве.
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.