PHP 関数 foo があるとします。
function foo($firstName = 'john', $lastName = 'doe') {
echo $firstName . " " . $lastName;
}
// foo(); --> john doe
2 番目のオプション パラメータのみを指定する方法はありますか?
例:
foo($lastName='smith'); // output: john smith
PHP 関数 foo があるとします。
function foo($firstName = 'john', $lastName = 'doe') {
echo $firstName . " " . $lastName;
}
// foo(); --> john doe
2 番目のオプション パラメータのみを指定する方法はありますか?
例:
foo($lastName='smith'); // output: john smith
PHPは、関数自体の名前付きパラメーターをサポートしていません。ただし、これを回避する方法はいくつかあります。
デフォルト値をより簡単に設定できる配列手法のバリエーション:
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
複数のオプションのパラメーターがある場合、1つの解決策は、ハッシュ配列である単一のパラメーターを渡すことです。
function foo(array $params = array()) {
$firstName = array_key_exists("firstName", $params) ?
$params["firstName"] : "";
$lastName = array_key_exists("lastName", $params) ?
$params["lastName"] : "";
echo $firstName . " " . $lastName;
}
foo(['lastName'=>'smith']);
もちろん、このソリューションでは、ハッシュ配列のフィールドが存在するか、スペルが正しいかどうかの検証はありません。検証するのはあなた次第です。
あなたが望む方法:いいえ。
NULLなどの特別なマークを使用して、値が指定されていないことに注意することができます。
function foo($firstName, $lastName = 'doe') {
if (is_null($firstName))
$firstName = 'john';
echo $firstName . " " . $lastName;
}
foo(null, 'smith');
いいえ。これを行う通常の方法は、文字列の長さ、入力などのように、どのパラメーターが暗示されているかを判断するヒューリスティックを使用することです。
一般的に言えば、最も必要なものから最も必要のないものへの順序でパラメーターを取得する関数を作成します。
2.5年前にPHPを使い始めたとき、このソリューションがSOにあったことを願っています。私が作成した例ではうまく機能しますが、完全に拡張可能であってはならない理由がわかりません。以前に提案されたものに比べて、次の利点があります。
(i) 関数内のパラメーターへのすべてのアクセスは、配列アクセスを要求するのではなく、パラメーターが完全に宣言されているかのように、名前付き変数によって行われます。
(ii) 既存の機能を非常に迅速かつ簡単に適応させることができる
(iii) どの関数に対しても 1 行の追加コードしか必要ありません (関数シグネチャで行う既定のパラメーターを定義するという避けられない必要性に加えて、代わりにそれらを配列で定義します)。追加の行の功績は完全に Bill Karwin によるものです。この行は、すべての関数で同じです。
方法
必須パラメーターとオプションの配列を使用して関数を定義します
オプションのパラメータをローカル変数として宣言します
重要なのは、配列を介して渡したものを使用して、オプションのパラメーターの事前に宣言されたデフォルト値を置き換えることです。
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'));
結果:
犬はロバの上に立った
猫はロバの上に座った
犬がマットの上に立っていた
引数は位置順に渡す必要があります。パラメータ自体をスキップすることはできません。スキップするには、デフォルトのパラメーター値を指定する必要があります。おそらく、それはあなたが達成しようとしている目的を無効にします。
パラメーターを別の方法で受け入れるように関数を書き直すことなく、これを回避する呼び出し時の方法を次に示します。
$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']);
悲しいことに、あなたがやろうとしていることには、それを行うための「シンタックスシュガー」の方法がありません。それらはすべてさまざまな形式の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');
もちろん、ここでは配列引数を使用する方が簡単ですが、物事を行うための選択肢(悪い方法でも)が許可されています。
注目すべきことに、これはfoo(firstname =>'john');だけを実行できるため、Perlの方が優れています。
いいえ、ありませんが、配列を使用できます。
function foo ($nameArray) {
// Work out which values are missing?
echo $nameArray['firstName'] . " " . $nameArray['lastName'];
}
foo(array('lastName'=>'smith'));