戻り値の型指定
引数に型チェックができるようになったように、戻り値に関しても型の指定ができるようになりました。PHP 5では戻り値の型指定はできなかったので、こちらは完全に新しい仕様となり、リスト3のように型指定を行います。
function hoge() : [戻り値の型] { }
指定できる型は、引数の場合と同じであり、スカラー型とクラス(class)やインターフェース(interface)の指定が行えます。リスト4は戻り値の型指定を行った時のサンプルコードです。
function ret_string() : string{ return -1; } function ret_int() : int{ return "a"; } var_dump(ret_string()); //(1)string(2) "-1" var_dump(ret_int()); //(2)エラーになる
(1)では、戻り値でstringを指定していますが、-1を返していますので自動的な型変換により"-1"になります。これをエラーにするには、引数の場合と同じように自動的な型変換を行わないために、declare宣言を利用する必要があります。(2)はエラーとなります。
新しい演算子の導入
新しい演算子も2つほど導入されました。これら2つの演算子は既存のコードを簡単に記述できるシンタックスシュガーですが、直感的で短くコードが記述できるような変更となっています。
Null合体演算子
まず、最初に紹介するのがNull合体演算子(??)です。PHPでは連想配列を多用するケースが多々ありますが、その際にNULLであることをチェックする簡単に行うための演算子です。リスト5は、このNULLチェックをPHP5で行う際のコードとNull合体演算子を使った場合のサンプルコードですが、このコードを見ればすぐに利用方法がわかると思います。
$user1 = isset($_GET['id'])? $_GET['id']: 100; //(1)PHP5での記述 $user2 = $_GET['id'] ?? 101; //(2)PHP 7での記述
(1)はPHP 5で連想配列でのNULLをチェックする場合のコードですが、このコードを(2)のように??を使えば非常に短く記述ができます。三項演算子におけるNULLに限定した場合の記述方法とも言えます。
宇宙船演算子
宇宙船演算子は、2つの式を比較するときに0、1、-1のいずれかを返す演算子で、ソートでの比較関数を作る場合に使用できる演算子です。ソート比較関数を頻繁に作るというケースもあまりないので、それほど重宝はしないとは思いますが、リスト6のように宇宙演算子を利用するとわかりやすいコードは記述可能です。
function spaceship_sort($a,$b){ // return $a <=> $b; //(1)小さい順 return $b <=> $a; //(2)大きい順 } $list = [5,2,4,1,3]; usort($list,'spaceship_sort');
ソート比較関数の引数の順番と同じ並びで記述した場合には昇順(1)、逆に記述した場合が降順(2)となることを覚えておけば直感的にわかりやすいコードになります。
Unicodeエスケープ形式での記述サポート
Unicodeのエスケープ形式での記述は、いろいろな言語でサポートされていますが、PHPでもサポートされることになりました。
リスト7はUnicodeエスケープ形式で記述した際のサンプルコードです。
echo "\u{41}\u{42}\u{43}"; //(1)ABC echo "\x41\x42\x43"; //(2) 今までサポートされていた表記方法(xFF(8bit)以上は記述できない) echo "\u{9AD9}"; //(3)はしご高
例えば「ABC」は(1)もしくは(2)のようにエスケープ形式では表記できます。しかし、8bit以上は(2)の方法では表記できませんが、(3)のように表記できるようになりました。
無名クラス・無名関数(Closure)
無名クラスは、様々な言語でサポートされている仕様ですが、PHPでもサポートされることになりました。また、無名関数(Closure)については、PHP 5.3からサポートされている仕様ではありますが、より使いやすく変更が行われています。無名クラスや無名関数を使うことで、一度しか使わないコードや、処理を近くにわかりやすく記述したい場合などにより完結に処理が記述することができるようになります。
無名クラス
無名クラスの作成は、new classで作成します。また、他のクラス、もしくはインターフェースを継承する場合には、new class extendsもしくはnew class implementsのようになり、リスト8は処理の実体を他のクラスに委譲したようなアプリケーションにおいて、インターフェースを継承した無名クラスを使ったときのサンプルコードです。
interface Handler{ // (1)無名クラスが実装するインターフェース public function accept(string $msg); public function reject(string $msg); } class Application { public function exec(Handler $handler){ try { $result = "hoge"; // 何らかの複雑な処理の結果を想定 $handler->accept($result); } catch(Exception $ex){ $handler->reject($ex->getMessage()); } } } $app = new Application; $app->exec(new class implements Handler { //(2)無名クラスの作成 public function accept(string $msg){ echo sprintf("[OK]\t%s".PHP_EOL,"app",$msg); } public function reject(string $msg){ echo sprintf("[NG]\t%s".PHP_EOL,"app",$msg); } });
(1)では、無名クラスが実装するインターフェースを定義しています。このインターフェースは、処理が成功したときの処理と、失敗したときの処理を定義するようにしています。そして、(2)のように処理を具体的に行う記述は、無名クラスを用いて記述しています。このように、無名関数を用いると、処理の流れの近くで定義を記述することができるので処理が見通しやすくなる効果があります。
無名関数(Closure)
無名関数(Closure)は、PHP 5.3からサポートされている仕様ですが、PHP 5.4で$thisの利用がサポートされ、そして、PHP 7ではcallという関数が追加されました。JavaScriptと同じようにcall()関数で無名関数が実行できるようになり、また、引数に$thisが示すオブジェクトを指定できるようになりました。
class Hoge{ private $name; private $prefix = "こんにちは "; function __construct($name){ $this->name = $name; } public function hello($postfix = ''){ return function() use($postfix){ //(1) 関数を返す。またhello関数の引数を使うためにuseを指定する return $this->prefix.$this->name.$postfix; }; } } $obj1 = new Hoge("hoge"); //(2)hello関数を作成する為のオブジェクトを作成 $func = $obj1->hello('さん'); var_dump($func()); //(3)string(26) "こんにちは hogeさん" var_dump($func->call($obj1)); //(4)string(26) "こんにちは hogeさん"
(1)のhello関数の中では今回利用する無名関数を作成してしています。無名関数内で関数外のスコープから変数を取得するためにuseを用いています。
(2)は、hello関数を作成するクラスのインスタンスを作成しています。また、同時にhello関数内の$thisで示されるインスタンスでもあります。
(3)はPHP5.4以降での関数の実行方法ですが、PHP 7からは(4)のように実行も可能です。