PHP7
とりあえず動くPHPが大好きな皆さんこんにちは。
そんなゆるふわなPHPをタイプセーフ(型安全)に書けたらもっと好きになるのになーと思ったことはありませんか?僕はあります。
そんな熱い要望に応えた(と勝手に思っている)PHP7が正式にリリースされて、はや半年以上。
既に試されている方も多いと思いますが、PHPをもっと好きになるためにPHP7の三大新機能を使って、このたび僕もタイプセーフなPHPを書いてみましたので、その結果をまとめさせていただきます。
ちなみに、PHP7の三大新機能とは…
- スカラー型宣言
-
int
,string
,bool
がタイプヒンティングに使えるようになった。
-
- 戻り値の型宣言
- 引数と同様に関数の戻り値でも型宣言出来るようになった。
- Null合体演算子
- 三項演算子と
isset()
地獄から解放される。??
と書く。
- 三項演算子と
のことです。(僕が勝手に呼んでいる)
実験
いろいろ書いてみたので、順番に紹介させていただきます。
なお、PHPのバージョンは 7.0.7
です。
検証①
サンプルは英語、数学、国語の点数を合算して、合計点を表示するだけのプログラムです。
早速、書いてみます。
<?php
function calculate_total_score(array $scores): int
{
$english = $scores['english'] ?? 0;
$math = $scores['math'] ?? 0;
$japanese = $scores['japanese'] ?? 0;
$totalScore = $english + $math + $japanese;
return $totalScore;
}
$scores = array();
$scores['english'] = 70;
$scores['math'] = 80;
$scores['japanese'] = 60;
$totalScore = calculate_total_score($scores);
echo '合計点は' . $totalScore . 'でした。' . "\n";
$ php seven1.php
合計点は210でした。
まず、関数の引数にスカラー型が利用出来るようになったので (array $scores)
と書きます。
そして、関数の戻り値の型を指定するためには引数の後に : int
と書きます。
これでタイプセーフなPHPが書けます!タイプセーフなPHPとか最強かよ!
検証②
では、ここで本当にタイプセーフなのか検証していきましょう。
<?php
function calculate_total_score(int $scores): int
{
$english = $scores['english'] ?? 0;
$math = $scores['math'] ?? 0;
$japanese = $scores['japanese'] ?? 0;
$totalScore = $english + $math + $japanese;
return $totalScore;
}
$scores = array();
$scores['english'] = 70;
$scores['math'] = 80;
$scores['japanese'] = 60;
$totalScore = calculate_total_score($scores);
echo '合計点は' . $totalScore . 'でした。' . "\n";
引数の型指定を array
から int
に変更しました。
実行結果は以下です。
$ php seven2.php
Fatal error: Uncaught TypeError: Argument 1 passed to calculate_total_score() must be of the type integer, array given
きちんとエラーになりました!PHP7最高かよ!
検証③
同じように戻り値も変えてみましょう。
<?php
function calculate_total_score(array $scores): array
{
$english = $scores['english'] ?? 0;
$math = $scores['math'] ?? 0;
$japanese = $scores['japanese'] ?? 0;
$totalScore = $english + $math + $japanese;
return $totalScore;
}
$scores = array();
$scores['english'] = 70;
$scores['math'] = 80;
$scores['japanese'] = 60;
$totalScore = calculate_total_score($scores);
echo '合計点は' . $totalScore . 'でした。' . "\n";
$ php seven3.php
Fatal error: Uncaught TypeError: Return value of calculate_total_score() must be of the type array, integer returned
ちゃんと怒られますね。やっぱりPHP7最高だわ。
これでめでたしめでたし…と思いきや…。
検証④
念のため、もう少し検証してみましょう。
検証③では戻り値の型指定をarray
にしていましたが string
にしてみましょう。
<?php
function calculate_total_score(array $scores): string
{
$english = $scores['english'] ?? 0;
$math = $scores['math'] ?? 0;
$japanese = $scores['japanese'] ?? 0;
$totalScore = $english + $math + $japanese;
return $totalScore;
}
$scores = array();
$scores['english'] = 70;
$scores['math'] = 80;
$scores['japanese'] = 60;
$totalScore = calculate_total_score($scores);
echo '合計点は' . $totalScore . 'でした。' . "\n";
これを実行すると…
$ php seven4.php
合計点は210でした。
/(^o^)\ナンテコッタイ
さすがPHPだぜ。。一筋縄ではいかない。でも、これぐらいならまだいいですよ。
検証⑤
では、戻り値の型指定を bool
にしてみましょう。
<?php
function calculate_total_score(array $scores): bool
{
$english = $scores['english'] ?? 0;
$math = $scores['math'] ?? 0;
$japanese = $scores['japanese'] ?? 0;
$totalScore = $english + $math + $japanese;
return $totalScore;
}
$scores = array();
$scores['english'] = 70;
$scores['math'] = 80;
$scores['japanese'] = 60;
$totalScore = calculate_total_score($scores);
echo '合計点は' . $totalScore . 'でした。' . "\n";
これを実行すると…
$ php seven5.php
合計点は1でした。
\(^o^)/オワタ
ちゃんと実行された上に1点になってしまいました。
もうPHPやだ。。Rubyしよ。。
検証⑥
PHPにタイプセーフは早かったのか…と半ば諦めながら、マニュアルを虚ろな目で眺めていると、こんな記述が。
スカラー 型宣言 には二つの方式があります。デフォルトの自動変換 (coercive) モードと、 厳密に判断する strict モードです。
なんだってー!!
もしかして strict
モードにすればよいのでは??
ということでやってみました。
<?php
declare(strict_types=1);
function calculate_total_score(array $scores): bool
{
$english = $scores['english'] ?? 0;
$math = $scores['math'] ?? 0;
$japanese = $scores['japanese'] ?? 0;
$totalScore = $english + $math + $japanese;
return $totalScore;
}
$scores = array();
$scores['english'] = 70;
$scores['math'] = 80;
$scores['japanese'] = 60;
$totalScore = calculate_total_score($scores);
echo '合計点は' . $totalScore . 'でした。' . "\n";
strict
モードにするには declare(strict_types=1);
と書きます。
これで実行すると、
$ php seven6.php
PHP Fatal error: Uncaught TypeError: Return value of calculate_total_score() must be of the type boolean, integer returned
キタ━━━━(゚∀゚)━━━━!!
ちゃんとエラーが出ました。
結論
- PHPでタイプセーフなコードを書きたいときは strict モードにしましょう。
- PHPのせいにせずちゃんとマニュアルを読みましょう(自戒)
- PHP7最高!
参考サイト
『PHP: 新機能 - Manual』
http://php.net/manual/ja/migration70.new-features.php