関数の引数

引数のリストにより関数へ情報を渡すことができます。 このリストは、カンマで区切られた式のリストです。 引数の評価は、左から右の順番で行われます。

PHP は、値渡し(デフォルト)、 リファレンス渡しデフォルト引数値 をサポートしています。また、 可変長引数リスト や、 名前付き引数 もサポートしています。

例1 関数に配列を渡す

<?php
function takes_array($input)
{
    echo 
"$input[0] + $input[1] = "$input[0]+$input[1];
}
?>

PHP 8.0.0 以降では、引数リストの最後にカンマを付けることができます。 このカンマは無視されます。 これは、引数リストや変数名が長かったりした場合に、 引数を縦に並べるのに便利です。

例2 関数の引数リストの最後にカンマを付ける

<?php
function takes_many_args(
    
$first_arg,
    
$second_arg,
    
$a_very_long_argument_name,
    
$arg_with_default 5,
    
$again 'a default string'// この最後のカンマは、8.0.0 より前では許されません。
)
{
    
// ...
}
?>

PHP 8.0.0 以降では、オプションの引数の後に、必須の引数を続けることは、 推奨されなくなります。 一般的には、デフォルト値を削除することで解決できます。 このルールの唯一の例外は、Type $param = null と書かれた引数です。 null をデフォルトにすることは、型が暗黙のうちに nullable であることを示しています。 この書き方はまだ許可されていますが、明示的に nullable 型を使うことを推奨します。

例3 オプションの引数の後に、必須の引数を続ける

<?php
function foo($a = [], $b) {} // PHP 8.0.0 より前
function foo($a$b) {}      // PHP 8.0.0 以後

function bar(A $a null$b) {} // PHP 8.0.0 でもまだ許可されています
function bar(?A $a$b) {}       // お勧めの書き方
?>

引数のリファレンス渡し

デフォルトで、関数の引数は値で渡されます。(このため、関数の内部で 引数の値を変更しても関数の外側では値は変化しません。)関数がその引 数を修正できるようにするには、その引数をリファレンス渡しとする必要があり ます。

関数の引数を常にリファレンス渡しとしたい場合には、関数定義において アンパサンド(&) を引数名の前に付加することができます。

例4 関数のパラメータのリファレンス渡し

<?php
function add_some_extra(&$string)
{
    
$string .= 'and something extra.';
}
$str 'This is a string, ';
add_some_extra($str);
echo 
$str;    // 出力は 'This is a string, and something extra.' となります
?>

リファレンス渡しが想定されているところに、値渡しを行うとエラーになります。

デフォルト引数値

関数は、スカラー引数に関して次のように C++ スタイルのデフォルト値を 定義することができます。

例5 関数におけるデフォルトパラメータの使用法

<?php
function makecoffee($type "cappuccino")
{
    return 
"Making a cup of $type.\n";
}
echo 
makecoffee();
echo 
makecoffee(null);
echo 
makecoffee("espresso");
?>

上の例の出力は以下となります。

Making a cup of cappuccino.
Making a cup of .
Making a cup of espresso.

PHPでは、配列および特殊な型 null をデフォルト値とすることも可能です。 例えば、

例6 スカラー型以外をデフォルト値として使用する

<?php
function makecoffee($types = array("cappuccino"), $coffeeMaker NULL)
{
    
$device is_null($coffeeMaker) ? "hands" $coffeeMaker;
    return 
"Making a cup of ".join(", "$types)." with $device.\n";
}
echo 
makecoffee();
echo 
makecoffee(array("cappuccino""lavazza"), "teapot");
?>

デフォルト値は、定数式である必要があり、 (例えば) 変数やクラスのメンバーであってはなりません。

引数のデフォルト値を使用する際には、デフォルト値を有する引数はデ フォルト値がない引数の右側に全てある必要があることに注意して下さ い。そうでない場合、意図したような動作が行われません。次の簡単な コードを見てみましょう。

例7 関数の引数のデフォルト値の 間違った使用法

<?php
function makeyogurt($type "acidophilus"$flavour)
{
    return 
"Making a bowl of $type $flavour.\n";
}
 
echo 
makeyogurt("raspberry");   // 期待通りには動作しません。
?>

上の例の出力は以下となります。

Warning: Missing argument 2 in call to makeyogurt() in 
/usr/local/etc/httpd/htdocs/phptest/functest.html on line 41
Making a bowl of raspberry .

ここで、上の例を次のコードと比べてみましょう。

例8 関数の引数のデフォルト値の 正しい使用法

<?php
function makeyogurt($flavour$type "acidophilus")
{
    return 
"Making a bowl of $type $flavour.\n";
}
 
echo 
makeyogurt("raspberry");   // 期待通り動作します
?>

上の例の出力は以下となります。

Making a bowl of acidophilus raspberry.

注意: リファレンス渡しの引数にもデフォルト値を指定できます。

可変長引数リスト

PHP は ... を使った可変長引数をユーザー定義関数でサポートしています。

注意: func_num_args(), func_get_arg(), func_get_args() 関数を使えば、可変長引数を実現できますが、 このテクニックは推奨されません。 なぜなら、... トークンが実装される前に使われていたものだからです。

引数リストに ... トークンを含めることで、 その関数が可変長の引数を受け取ることを示せます。 引数は、指定した変数に配列として渡されます。次の例を参照ください。

例9 ... を使った、可変長引数へのアクセス

<?php
function sum(...$numbers) {
    
$acc 0;
    foreach (
$numbers as $n) {
        
$acc += $n;
    }
    return 
$acc;
}

echo 
sum(1234);
?>

上の例の出力は以下となります。

10

関数を呼び出すときに ... を使うと、 配列変数や Traversable クラスを引数リストに含めることができます。

例10 引数での ... の使用例

<?php
function add($a$b) {
    return 
$a $b;
}

echo 
add(...[12])."\n";

$a = [12];
echo 
add(...$a);
?>

上の例の出力は以下となります。

3
3

通常の引数を、... の前に指定することもできます。 この場合は、通常の引数リストにマッチしなかったのこりの引数が ... による配列に追加されます。

... トークンの前に、 型宣言 を付加することもできます。 型宣言がある場合、... が取り込むすべての引数はその型に従わなければいけません。

例11 型宣言つきの可変長引数

<?php
function total_intervals($unitDateInterval ...$intervals) {
    
$time 0;
    foreach (
$intervals as $interval) {
        
$time += $interval->$unit;
    }
    return 
$time;
}

$a = new DateInterval('P1D');
$b = new DateInterval('P2D');
echo 
total_intervals('d'$a$b).' days';

// これは失敗します。null は DateInterval オブジェクトではないからです。
echo total_intervals('d'null);
?>

上の例の出力は以下となります。

3 days
Catchable fatal error: Argument 2 passed to total_intervals() must be an instance of DateInterval, null given, called in - on line 14 and defined in - on line 2

可変長引数の リファレンス渡し もできます。その場合は、... の前にアンパサンド (&) を付加します。

古いバージョンの PHP

可変長引数に関して特別な構文は必要としません。しかし、関数の引数にアクセスするには func_num_args()func_get_arg() および func_get_args() といった関数を使う必要があります。

先ほどの最初の例を、古いバージョンの PHP で実装すると、以下のようになります。

例12 可変長引数へのアクセス (古いバージョンのPHP)

<?php
function sum() {
    
$acc 0;
    foreach (
func_get_args() as $n) {
        
$acc += $n;
    }
    return 
$acc;
}

echo 
sum(1234);
?>

上の例の出力は以下となります。

10

名前付き引数

既にある、位置を指定した引数を拡張する形で、PHP 8.0.0 から名前付き引数が導入されました。 名前付き引数は、位置ではなく、名前ベースで引数を渡すことを可能にします。 これによって、引数の意味が自己文書化(self-documenting)され、 引数を任意の順番で渡せるようになり、任意のデフォルト値を持つ引数をスキップできるようになります。

名前付き引数は、引数の名前の後にコロンを付けたものを、値の前に付けることで指定します。 引数の名前に予約語を使うことも許されています。 引数の名前は識別子でなければならず、動的に指定することは出来ません。

例13 名前付き引数の文法

<?php
myFunction
(paramName$value);
array_foobar(array: $value);

// 以下の書き方はサポートされていません
function_name($variableStoringParamName$value);
?>

例14 位置を指定した引数と、名前付き引数

<?php
// 位置を指定した引数の場合:
array_fill(010050);

// 名前付き引数の場合:
array_fill(start_index0count100value50);
?>

名前付き引数は、渡す順番は関係ありません。

例15 上と同じ例を、引数の順番を変えて渡す

<?php
array_fill
(value50num100start_index0);
?>

名前付き引数は、位置を指定した引数と組み合わせることが出来ます。 そうした場合、名前付き引数は、位置を指定した引数の後に置かなければいけません。 オプションの引数だけをいくつか、指定することもできます。 その場合も、名前付き引数の順番は関係ありません。

例16 位置を指定した引数と、名前付き引数を組み合わせる

<?php
htmlspecialchars
($stringdouble_encodefalse);
// 上記は、以下と同等です。
htmlspecialchars($stringENT_COMPAT ENT_HTML401'UTF-8'false);
?>

同じ引数を複数回渡すと、Error 例外が発生します。

例17 同じ引数を複数回渡すと、Error 例外が発生する

<?php
function foo($param) { ... }

foo(param1param2);
// Error: Named parameter $param overwrites previous argument
foo(1param2);
// Error: Named parameter $param overwrites previous argument
?>