いつも通りのある日の事、ヤバそうなコードに出会いました。
yabai.php
function write_test($param = '1', $param = '2')
{
return $param . PHP_EOL;
}
oh...同名の引数が二つ...どういうこと?
IDEの警告とかで怒られないのかなこれ?というかなんでユニットテスト通過してるの?
怖すぎるので、どういう挙動になるのか調べることにしました。
こういう時、まず見るべきは公式ドキュメントだと偉い人がいっていたので確認してみます。
PHP:関数の引数-Manual
うん、書いてなさそう。
公式ドキュメントは諦めて、個人サイト様やQiitaの記事なんかも軽く探してみます。...オーバーロードがどうとか変数のスコープがどうたらとかいう記事くらいしか引っ掛かりませんでした。
己のググり力の無さに泣きつつ、仕方ないのでどういう挙動になるのか自分で検証しました。尚、PHPのverは5.5です。
デフォルト値がある場合
まずは今回出くわしたように引数にデフォルト値があるパターン。
テスト用コード
test.php
<?php
echo 'パターン1:' . write_test();
echo 'パターン2:' . write_test('A');
echo 'パターン3:' . write_test('A','B');
function write_test($param = 'a', $param = 'b')
{
return $param . PHP_EOL;
}
出力結果
パターン1:b
パターン2:b
パターン3:B
全てのパターンで後ろの$paramの値が使われていますね。
普通に通っちゃうんですね。怖いですね。
デフォルト値がない場合
次にデフォルト値を指定していないパターンも確認。
テスト用コード
test.php
<?php
echo 'パターン1:' . write_test();
echo 'パターン2:' . write_test('A');
echo 'パターン3:' . write_test('A','B');
function write_test($param, $param)
{
return $param . PHP_EOL;
}
出力結果
PHP Warning: Missing argument 1 for write_test(), called in /mnt/test.php on line 2 and defined in /mnt/test.php on line 6
PHP Warning: Missing argument 2 for write_test(), called in /mnt/test.php on line 2 and defined in /mnt/test.php on line 6
PHP Notice: Undefined variable: param in /mnt/test.php on line 8
パターン1:
PHP Warning: Missing argument 2 for write_test(), called in /mnt/test.php on line 3 and defined in /mnt/test.php on line 6
パターン2:A
パターン3:B
一応WarningとNoticeがでてきました。
それはいいんですが、パターン2の挙動が怖すぎます。
思わずPHP君の悪口書きそうになりましたが、そもそもこんな関数作るなよって話ですね。