ツイート
シェア
LINEで送る
B! はてぶでブックマーク
Pocketでブックマーク
RSSフィード

PHP8, 関数のパラメータ順が関係なくなる。名前付きパラメータの追加。

php
イラストダウンロードサイト【イラストAC】
の画像をもとに加工しています。

PHP8では名前付きパラメータ(引数)が使えるようになりました。関数呼び出しのパラメータの順番が無視できるようになります。

とくに、デフォルト値が指定されたパラメータを使うときに便利。

PHP8はデータの厳格化がポイントになってるんですがその一環です。

2020年11月26日、5年ぶりにphpのメジャーバージョンが上がりました。php8です。

メジャーアップデートだけに変更点も大きいです。

関数を呼び出すときに、パラメータ名を指定できるようになったのもそのひとつ。

まずは使い方を見てみましょう。そのあとに、どれだけ便利になったのかを見ていきます。

名前付きパラメータ

名前付きパラメータは、ソースコードを見たほうが早いです。

<?php

function sum1($data1 = 2, $data2 = 3 ) {
    echo $data1 . ' + ' . $data2 . ' = ';
    return $data1 + $data2;
}

$inp1 = 3;
$inp2 = 5;

echo sum1( data1: $inp1, data2: $inp2 ) . PHP_EOL;
実行結果
php80 sample.php
3 + 5 = 8

[ パラメータ変数名 ] :(コロン) [入力値]

functionのパラメータ変数名を使うので、修正するのは呼び出し元だけ。修正内容もかんたんです。

もちろんですが、PHP7ではエラーになります。

PHP7で実行すると
php sample.php
PHP Parse error:  syntax error, unexpected ':', expecting ')' in /home/sample/sample.php on line 11

『コロンなんて知らねーよ!』というエラーです。

名前付きパラメータと従来のパラメータの共存

これまでの名前無しパラメータと、名前付きパラメータは共存できます。しかし、注意点が。

混在パラメータにはルールがあり、それに従わないとエラーになります。

名前付きパラメータの後ろに名前無しは使えない

名前付きパラメータの後ろには名前無しパラメータは使えません。

<?php

function sample( $param1 = 'aaa' , $param2 = 'bbb' , $param3 = null ) {
    echo 'param1: ' . var_export( $param1, true ) . PHP_EOL;
    echo 'param2: ' . var_export( $param2, true ) . PHP_EOL;
    echo 'param3: ' . var_export( $param3, true ) . PHP_EOL;
}

sample( param1: '111', '222', '333' );
エラー発生
php80 sample2.php
PHP Fatal error:  Cannot use positional argument after named argument in /home/sample/sample2.php on line 9

従来のパラメータは、名前付きパラメータに対して『位置パラメータ』と呼ぶらしい。

パラメータの順番が一致しないといけないからでしょう。

名前付きパラメータの後ろに使えない理由は、その位置がずれることがあるから。

もちろんですけど、位置パラメータが前にある分にはOKです。

sample( '111', param3: 'sample', param2: '222' );
実行結果
php80 sample2.php
param1: '111'
param2: '222'
param3: 'sample'

名前付きパラメータの順番は関係ありません。

もうひとつは、位置パラメータは順番が一致しないといけません。

sample( '111', '222', param3: 'sample' );
実行結果
php80 sample2.php
param1: '111'
param2: '222'
param3: 'sample'

名前付きパラメータでの上書き禁止

位置パラメータを使っているのに、それを名前付きパラメータでも使っているとNGです。

sample( '111', '222', param2: 'sample' );
実行結果
PHP Fatal error:  Uncaught Error: Named parameter $param2 overwrites previous argument in /home/sample/sample2.php:9
Stack trace:
#0 {main}
  thrown in /home/sample/sample2.php on line 9

『オーバーライド(上書き)してんじゃねーよ!』って出ます。

デフォルト値の意味を考えよう

名前付きパラメータが出てきたことで、パラメータのデフォルト値の意味が変わっています。

ひとつは今までと同じ、『指定されなかったときのデフォルト値』。

そして新しく出てきたのは、『必須パラメータか否か』

デフォルト値必須パラメータ
あり
なし
sample2.php
<?php

function sample( $param1=null , $param2 , $param3, $param4 ) {
    echo 'param1: ' . var_export( $param1, true ) . PHP_EOL;
    echo 'param2: ' . var_export( $param2, true ) . PHP_EOL;
    echo 'param3: ' . var_export( $param3, true ) . PHP_EOL;
    echo 'param4: ' . var_export( $param4, true ) . PHP_EOL;
}

sample( '111', param4: '444', param3: '333' );
必須パラメータエラー
php80 sample2.php
PHP Fatal error:  Uncaught ArgumentCountError: sample(): Argument #2 ($param2) not passed in /home/sample/sample2.php:3
Stack trace:
#0 /home/sample/sample2.php(10): sample()
#1 {main}
  thrown in /home/sample/sample2.php on line 3
修正サンプル
sample( '111', '222', param4: '444', param3: '333' );
// または
// sample( '111', param4: '444', param3: '333', param2: '222' );
実行結果
php80 sample2.php
param1: '111'
param2: '222'
param3: '333'
param4: '444'

2種類のパラメータの共存はやめよう!

位置パラメータ(従来のパラメータ)と名前付きパラメータの共存は、はっきりいってやめたほうがいい。混乱の元だから。

例えばこのコードを実行します。

<?php

function sample( $param1=null , $param2 , $param3, $param4 ) {
    echo 'param1: ' . var_export( $param1, true ) . PHP_EOL;
    echo 'param2: ' . var_export( $param2, true ) . PHP_EOL;
    echo 'param3: ' . var_export( $param3, true ) . PHP_EOL;
    echo 'param4: ' . var_export( $param4, true ) . PHP_EOL;
}

sample( '111', '222', param3: '333' );

もちろん、param4が必須パラメータなので、エラーになります。

param4エラー
php80 sample2.php
PHP Fatal error:  Uncaught ArgumentCountError: Too few arguments to function sample(), 3 passed in /home/sample/sample2.php on line 10 and exactly 4 expected in /home/sample/sample2.php:3
Stack trace:
#0 /home/sample/sample2.php(10): sample()
#1 {main}
  thrown in /home/sample/sample2.php on line 3

そうすると、こういう修正をしがちです。

sample( '111', '222', param3: '333', '444' );

が、これもエラー。今度は、名前付きパラメータの後ろに位置パラメータがあるから。

php80 sample2.php
PHP Fatal error:  Cannot use positional argument after named argument in /home/sample/sample2.php on line 10

エラー発生。

修正してまたエラー発生。

(最悪、これが続く。)

こういうことが起きると普段ならできるのに、負のループに陥りやすいので時間がもったいない。

混乱の原因になるものを潰していくのもプログラミングのコツです。こういうコーディングはやめましょう。

名前付きパラメータは、使うなら全パラメータに使う。

使わないなら全パラメータに使わない。

共存はやめる。

というか、関数の呼び出し元でパラメータの意味が分かるし、コーディング的には絶対に使ったほうがいい。読みやすいから。

関数の呼び出し元でパラメータの意味が分かると、バグのリサーチで関数内まで読まなくていいこともあって助かる。

バグの予防にもなる。

パラメータの指定がスッキリ!

長々といろいろなことを言ってきましたが、名前付きパラメータの一番のメリットは、関数呼び出しのパラメータ数が最小限で済むことです。

<?php

function sample( $param1 = null , $param2 = true , $param3 ) {
    echo 'param1: ' . var_export( $param1, true ) . PHP_EOL;
    echo 'param2: ' . var_export( $param2, true ) . PHP_EOL;
    echo 'param3: ' . var_export( $param3, true ) . PHP_EOL;
}

param1, param2はデフォルト値のままにしてsample()を使いたいとき、今まではこんな感じで使っていました。

$param3 = "sample";
sample( null, true, $param3);

せっかく関数のデフォルト値が設定されているのに、関数を使うときにはそのデフォルト値が何なのかを調べて指定する必要がありました。

(順序も守らないといけないし。)

名前付きパラメータでは、デフォルト値を知る必要はありません。

$param3 = "sample";
sample( param3: $param3);

スッキリしていいですね? また、デフォルト値が変わっても関数を呼び出す側で修正する必要がありません。

個人的には、名前付きパラメータを使うのをコーディング規約に入れてもいいんじゃないかと思います。

PHP8以降でしか使わないという前提があれば。

PHP7でも動くようにする場合は使えない。もしくはPHPバージョンごとに処理を分ける対応が必要。

あえて作業が増えるようなら、PHP7のサポートが終わるまで名前付きパラメータを使わない選択肢もある。

前の投稿
PHP8, Nullsafe, オブジェクトのnullチェックを省略するプロパティ・メソッド参照
PHP8, 関数のパラメータの型を守らないとエラーになる。戻り値も。
次の投稿
コメントを残す

*