PHP 関数の引数あれこれ

# 概要

- 今更ながらPHPの関数の引数についてちゃんとまとめてみた。

# 関数に引数を渡す

- 関数定義時に引数の受け取り処理を記載してあげれば引数を関数の範囲内で使う事ができる。

    ```php
    <?php
    
    function echoArg($str) {
        echo $str;
    }
    
    // XXXと出力される。
    echoArg('XXX');
    ```

# 関数の引数にデフォルト値を設定する

- 引数受け取り処理に`=`で記載することでデフォルト値を設定する事ができる。
- スカラー型（一般の値）、配列型、null型、オブジェクト型（PHP8.1から）をデフォルト値として指定する事ができる。

    ```php
    <?php
    
    function echoArg($str = 'YYY') {
        echo $str;
    }
    
    // YYYと出力される。
    echoArg();
    ```

- 注意点
    - 一切引数が渡されなかった場合のみデフォルト値が適用される。
    - 引数でnullが渡されたときはデフォルト値ではなくnullが渡される。
- 下記の場合はnullがechoされるので何も出力されない。

    ```php
    <?php
    
    function echoArg($str = YYY) {
        echo $str;
    }
    
    echoArg(null);
    ```

# 関数に引数を参照渡しする

- 渡される変数の定義箇所の頭に`&`を付与することでデータを参照渡しする事ができる。

    ```php
    <?php
    
    function foo(&$str)
    {
        $str .= 'YYY';
    }
    
    $arg = 'XXX';
    
    // 引数として渡す変数$argを直接更新する
    foo($arg);
    
    // XXXXYYYと出力される
    echo $arg;
    ```

# 引数の型を指定する

- 関数の引数設定の直前に型宣言をすることで引数で渡されるデータの型を指定する事ができる。一致しなかったらTypeErrorが返される。

    ```php
    <?php
    
    function foo(string $str1) {
        echo $str1;
        
    }
    
    echo foo('XXX');
    ```

- 上記の場合、引数の型はstring型が指定されているのでそれ以外を渡すとエラーになる。
# 関数に複数の引数を渡す

- 下記の様にカンマで区切ることで関数が複数の引数を受け取ることが可能になる。（最後の引数のあとにカンマを記載するのはPHP8以前だとエラーになるので注意）

    ```php
    <?php
    
    function echoArg($str1, $str2,) {
        echo $str1 . $str2;
    }
    
    echoArg('XXX', 'YYY');
    ```

- 複数の引数を渡すときでもデフォルト値を設定することはできる。
- しかし、引数の順番に注意する。
- 下記の様にデフォルト値の存在しない引数（nullableではない引数） → デフォルト値の存在する引数（nullableな引数）のように記載すること。

    ```php
    <?php
    
    function foo($str1, $str2 = 'YYY')
    {
        echo $str1 . $str2;
    }
    
    foo('XXX');
    ```

- nullableな引数 → nullableではない引数の定義はPHP８以上では非推奨になる。
- 理由は下記の様な関数呼び出しはすることができず、デフォルト値が使用されることがないため。

    ```php
    <?php
    
    function foo($str2 = 'YYY', $str1)
    {
        echo $str1 . $str2;
    }
    
    // こんな書き方ができればデフォルト値は使われるがこんな記載はできない。
    //foo( , 'XXX');
    // 下記の様な呼び出し方しかされないが、デフォルト値が使われないだけでなく、nullableではない第二引数に何も渡されないのでエラーになる。
    foo('XXX');
    ```

# 可変長の引数を渡す

- 引数の個数が処理によって異なる場合は可変長の引数を渡す事ができる。

    ```php
    <?php
    
    function foo(...$str)
    {
        var_dump($str);
    }
    
    foo('XXX', 'YYY', 'ZZZ');
    ```

- 受け取った複数の引数は変数に配列として渡される。
- 注意
    - 可変長の引数受け取りが設定されている状態で引数が渡されなくてもエラーにはならない。

    ```php
    <?php
    
    function foo(...$str)
    {
        var_dump($str);
    }
    
    // 下記はエラーにならない
    foo();
    ```

- 下記の様に呼び出し時に`...`を用いることで渡される配列の０番目を第一引数に、渡される配列の1番目を第二引数に設定指定処理することが可能らしい。

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

- 第一引数は通常の引数、第二引数は可変長の引数として設定することも可能

    ```php
    <?php
    
    function foo($str1, ...$str2) {
        echo $str1 . "\n";
        var_dump($str2);
        
    }
    
    echo foo('XXX', 'YYY', 'ZZZ');
    ```

- 上記を実行した場合第二引数以降が可変長の引数として配列で渡される。下記の様に出力される。

    ```
    XXX
    array(2) {
      [0]=>
      string(3) "YYY"
      [1]=>
      string(3) "ZZZ"
    }
    ```

- 可変長の引数指定では型宣言をすることもできる。この場合可変長の値すべてが当該の型と一致している必要がある。

    ```php
    <?php
    
    function foo(string ...$str)
    {
        var_dump($str);
    }
    
    foo('XXX', 'YYY', 'ZZZ');
    ```

- ちなみに...の前に&をつけることで可変長の引数も参照渡しする事ができる。

# 名前付き引数

- 今まで複数の引数は第一引数、第二引数・・・といった具合に関数に渡される引数の順番でしか識別できなかった。
- しかし、名前付き引数を用いることで呼び出し時の引数の順番が考慮されず、指定した名前で受け取られるようになる。
- これにより関数使用時に呼び出し先関数定義を読みに行って引数の順番を考える必要がなくなった。
- 今までは下記のように記載するしかなかった。

    ```php
    <?php
    
    function foo($hoge, $fuga, $piyo)
    {
        echo $hoge . "\n";
        echo $fuga . "\n";
        echo $piyo . "\n";
    }
    
    foo('XXX', 'YYY', 'ZZZ');
    ```

- これからは下記のように引数を渡すタイミングで引数名を指定することで引数の順番を考えなくて良くなる。（引数の名前指定は`引数名: 値`として設定する。）

    ```php
    <?php
    
    function foo($hoge, $fuga, $piyo)
    {
        echo $hoge . "\n";
        echo $fuga . "\n";
        echo $piyo . "\n";
    }
    
    foo(piyo: 'ZZZ', hoge: 'XXX', fuga: 'YYY');
    ```

# 参考文献

- [https://www.php.net/manual/ja/language.types.declarations.php](https://www.php.net/manual/ja/language.types.declarations.php)
- [https://www.php.net/manual/ja/functions.arguments.php](https://www.php.net/manual/ja/functions.arguments.php)