## 関数の引数

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

PHP は、値渡し(デフォルト)、 参照渡し、 デフォルト引数値 をサポートしています。また、 可変長引数リスト もサポートしてます。

例1 関数に配列を渡す

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

### 引数の参照渡し

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

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

例2 関数のパラメータの参照渡し

`<?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++ スタイルのデフォルト値を 定義することができます。

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

`<?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` をデフォルト値とすることも可能です。 例えば、

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

`<?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");
?>`

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

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

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

`<?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 .

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

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

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

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

    Making a bowl of acidophilus raspberry.

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

### 型宣言

> 注意:

> 型宣言は、PHP 5 ではタイプヒンティングとも呼ばれていました。

型宣言を使うと、、関数を呼ぶ際に渡すパラメータが特定の型であることを、関数の宣言時に要求できるようになります。 関数に渡された値が不正な型であった場合はエラーとなります。 PHP 5 では、このエラーは recoverable fatal error でした。 PHP 7 では、この場合に TypeError 例外をスローします。

型宣言を指定するには、型の名前をパラメータ名の前に追加します。 パラメータのデフォルト値が `NULL` である場合は、型宣言でも `NULL` 値を受け付けることができます。

#### 有効な型

型 | 説明 | 利用可能な PHP の最低バージョン
--- | --- | ---
クラス名 / インターフェイス名 | パラメータは、指定したクラスやインターフェイスのインスタンスでなければいけません。 | PHP 5.0.0
self | パラメータは、そのメソッドが定義されているクラスと同じクラスのインスタンスでなければいけません。 これが使えるのは、クラスメソッドやインスタンスメソッドだけです。 | PHP 5.0.0
array | パラメータは配列でなければいけません。 | PHP 5.1.0
callable | パラメータは callable でなければいけません。 | PHP 5.4.0
bool | パラメータは boolean 値でなければいけません。 | PHP 7.0.0
float | パラメータは float でなければいけません。 | PHP 7.0.0
int | パラメータは integer でなければいけません。 | PHP 7.0.0
string | パラメータは string でなければいけません。 | PHP 7.0.0
iterable | パラメータは、array または Traversable instanceof でなければいけません。 | PHP 7.1.0

警告

これらのスカラー方のエイリアスはサポートしていません。 エイリアスは、クラス名あるいはインターフェイス名として解釈されます。 つまり、パラメータや返り値の型として boolean を用いると、 bool であることを宣言したのではなく boolean クラス (あるいはインターフェイス) のインスタンスであると宣言したことになります。

`<?php
function test(boolean $param) {}
test(true);
?>`

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

     Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of boolean, boolean given, called in - on line 1 and defined in -:1

#### 例

例7 クラスの型宣言の基本例

`<?php
class C {}
class D extends C {}
// これは C を継承していません。
class E {}
function f(C $c) {
echo get_class($c)."\n";
}
f(new C);
f(new D);
f(new E);
?>`

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

    C
    D

    Fatal error: Uncaught TypeError: Argument 1 passed to f() must be an instance of C, instance of E given, called in - on line 14 and defined in -:8
    Stack trace:
    #0 -(14): f(Object(E))
    #1 {main}
      thrown in - on line 8

例8 インターフェイスの型宣言の基本例

`<?php
interface I { public function f(); }
class C implements I { public function f() {} }
// これは I を実装していません。
class E {}
function f(I $i) {
echo get_class($i)."\n";
}
f(new C);
f(new E);
?>`

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

    C

    Fatal error: Uncaught TypeError: Argument 1 passed to f() must implement interface I, instance of E given, called in - on line 13 and defined in -:8
    Stack trace:
    #0 -(13): f(Object(E))
    #1 {main}
      thrown in - on line 8

例9 Null を許可する型宣言

`<?php
class C {}
function f(C $c = null) {
var_dump($c);
}
f(new C);
f(null);
?>`

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

    object(C)#1 (0) {
    }
    NULL

#### 強い型付け

デフォルトでは、間違った型を渡された場合でも、可能な限りは来されている型に変換します。 たとえば、string を想定している関数のパラメータに integer が渡された場合は、その値を string 型として受け取ります。

ファイル単位で厳密な型チェックを有効にすることもできます。 この場合は、宣言されたとおりの型でない限りは受け付けず、 TypeError をスローします。 ただし、float が指定されているところに integer を渡した場合だけは例外です。 組み込み関数内からの関数呼び出しは、 strict_types 宣言の影響を受けません。

厳密な型チェックを有効にするには、declare 文を用いて strict_types を宣言します。

警告

厳密な型チェックを有効にすると、 戻り値の型宣言 にも影響を及ぼします。

> 注意:

> 厳密な型チェックが適用されるのは、それを有効にしたファイル の中からの関数呼び出しだけです。 そのファイル内で宣言されている関数に適用されるわけではありません。 厳密な型チェックを有効にしていないファイルから、 厳密な型チェックを有効にしたファイル内で定義された関数を呼び出した場合は、 呼び出し元の設定 (弱い型チェック) が適用されて、自動的に型変換を行います。

> 注意:

> 厳密な型チェックはスカラー型宣言に対してのみ定義されるものであり、 PHP 7.0.0 以降でなければ使えません。そもそもスカラー型宣言が追加されたのが PHP 7.0.0 だからです。

例10 厳密な型チェック

`<?php
declare(strict_types=1);
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1.5, 2.5));
?>`

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

    int(3)

    Fatal error: Uncaught TypeError: Argument 1 passed to sum() must be of the type integer, float given, called in - on line 9 and defined in -:4
    Stack trace:
    #0 -(9): sum(1.5, 2.5)
    #1 {main}
      thrown in - on line 4

例11 弱い型チェック

`<?php
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
// これらは integer 型として扱われます。出力例に注目！
var_dump(sum(1.5, 2.5));
?>`

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

    int(3)
    int(3)

例12 TypeError の捕捉

`<?php
declare(strict_types=1);
function sum(int $a, int $b) {
return $a + $b;
}
try {
var_dump(sum(1, 2));
var_dump(sum(1.5, 2.5));
} catch (TypeError $e) {
echo 'Error: '.$e->getMessage();
}
?>`

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

    int(3)
    Error: Argument 1 passed to sum() must be of the type integer, float given, called in - on line 10

### 可変長引数リスト

PHP は、可変長引数をユーザー定義関数でサポートしています。 PHP 5.6 以降では ... を使って実装されており、 PHP 5.5 以前では func_num_args(), func_get_arg(), func_get_args() 関数を使用します。

#### PHP 5.6 以降における ...

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

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

`<?php
function sum(...$numbers) {
$acc = 0;
foreach ($numbers as $n) {
$acc += $n;
}
return $acc;
}
echo sum(1, 2, 3, 4);
?>`

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

    10

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

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

`<?php
function add($a, $b) {
return $a + $b;
}
echo add(...[1, 2])."\n";
$a = [1, 2];
echo add(...$a);
?>`

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

    3
    3

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

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

例15 タイプヒントつきの可変長引数

`<?php
function total_intervals($unit, DateInterval ...$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 5.5 以前のバージョンで実装すると、以下のようになります。

例16 可変長引数へのアクセス (PHP 5.5 以前)

`<?php
function sum() {
$acc = 0;
foreach (func_get_args() as $n) {
$acc += $n;
}
return $acc;
}
echo sum(1, 2, 3, 4);
?>`

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

    10