SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

PHP 7がやってきた!!

新しい仕様でより進化したPHP 7を体験してみよう

PHP 7がやってきた!! 第1回

  • X ポスト
  • このエントリーをはてなブックマークに追加

ジェネレータ

 ジェネレータ自体はPHP 5.5で追加された機能で、繰り返しのデータを効率よく提供できるものです。同じような機能にはIteratorインターフェースを実装したクラスがありますが、複雑なクラスを自作することなく実装することができます。この処理が必要な主な理由には、実行時の消費メモリの節約があります。このジェネレータの機能においてPHP 7では最後の値のみの特別な扱いをするためのreturnと一部の処理を、別のジェネレータに委譲することが可能になりました。リスト10は、PHP 5.5とPHP 7でのサポートされたreturnを使ったサンプルコードです。

リスト10 ジェネレータの利用例(generator.php)
//(1)PHP 5.5の場合の実装例
function xrange5($start,$end){
    for($i = $start; $i < $end+1; $i++){
        yield $i;
    }
}
$it = xrange5(0,3);
$total = 0;
$cnt = 0;
foreach($it as $i){
    $cnt++;
    $total += $i;
}
if($cnt > 0 ){
    echo "合計値は[ $total ]です".PHP_EOL;
}
else{
    echo "合計処理は行われませんでした".PHP_EOL;
}

// PHP 7の場合の記述方法
function xrange7($start,$end){
    for($i = $start; $i < $end + 1; $i++){
        yield $i;
    }
    if($start < $end){
        return true;   //(2)returnで最後の値を指定可能
    }
    else{
        return false;
    }
}

$it = xrange7(0,3);
$total = 0;
foreach($it as $i){
    $total += $i;
}
if($it->getReturn()){    //(3)最後の値の取得
    echo "合計値は[ $total ]です".PHP_EOL;
}
else{
    echo "合計処理は行われませんでした".PHP_EOL;
}

 PHP 5.5で繰り返し処理の終了に応じた処理を記述した場合の例が(1)です。この処理をPHP 7でサポートされた方法で記述すると、(2)のように作成するジェネレータ内で最後の値をreturnで返します。この最後の値はforeach処理内では取得できず、(3)のようにgetReturn()関数を実行して取得できますので、こちらの値を使って特別な処理を記述します。このように最後を意識した処理がある場合には、その判断をジェネレータ側に隠蔽して実装する事ができます。

 また、ジェネレータは他のジェネレータに処理を以上することも出来ます。その場合には、yield fromの記述を使い、リスト11は別のジェネレータに処理を委譲した際のサンプルコードです。

リスト11 fromを使ったジェネレータの委譲の利用例(generator_from.php)
function range_from(){
    yield array(0,"-- 選択して下さい --");
    yield from range1();                 //(1)他のジェネレータへの委譲
    yield from [array(2,'千葉'),array(3,'埼玉')];  //(2)配列への委譲

    return "END_OF_RANGE_0"; //(3)getReturn()で取得できる値
}

function range1(){
    yield array(1,"東京");
    return "END_OF_RANGE_1"; //(4)この値は取得できません
}

$range = range_from();
foreach($range as $item){
    var_dump($item[1]); // "-- 選択して下さい --","東京","千葉","埼玉"の順に表示
}
var_dump($range->getReturn()); // string(14) "END_OF_RANGE_0"

 (1)のようにyield fromを用いることで別のジェネレータに処理を委譲することができます。また、委譲先は(2)のように配列でも問題ありません。ただし、getReturn()で取得できる値は親となるジェネレータで返している(3)の値であり、子となるジェネレータで指定した(4)の値は返せませんので注意して下さい。

エラー・例外の扱い

 PHP 7では、PHPコード内で取得可能であった最上位のクラスであるExceptionよりもさらに上位となるThrowableクラスが作成されました。また、コードの上のエラーを示すErrorクラスがThrowableクラスのサブクラスとして作成され、図1に示すようにコントロールできるエラーの範囲が広がりました。PHP 7で追加されたErrorクラスには表2のようなクラスがあります。

図1 PHP 7によるエラー・例外クラスの関係
図1 PHP 7によるエラー・例外クラスの関係
表2 追加されたエラークラス
クラス名 説明
TypeError 引数の型チェックや戻り値の型チェックでエラーになった場合
ParseError eval()などでPHPコードのパースが失敗した場合
AssertionError assert()によるアサーションが失敗した場合
ArithmeticError 数学的操作によるエラーが発生した場合
DivisionByZeroError ゼロの割り算の場合

 このため、リスト12のように今まではコード内で処理できなかったエラーも処理できるようになりました。また、finallyブロックはPHP 5.5で記述できるようになっています。

リスト12 Errorを取得する利用例(error.php)
function arg_int(int $num){
    return $num;
}
try {
    arg_int('a');
}
catch(Exception $ex){
    echo "Exception : ".get_class($ex)."-".$ex->getMessage().PHP_EOL;
}
catch(Error $err){  // Errorクラスを取得する
    echo "Error : ".get_class($err)." - ".$err->getMessage().PHP_EOL;
    // Error : TypeError - Argument 1 passed to arg_int() must be of the type integer, string given, called in ...
}
finally{
    // finally はPHP 5.5で追加されています
    echo "必ず実行されます".PHP_EOL;
}

最後に

 PHP 7で新たな言語仕様を見ていると、表面的なPHPコードにはあまり影響がないような印象を受けます。しかし、それでいて大きなパフォーマンスが得られることを考えると、素晴らしいバージョンアップのように思います。一方で、PHPコードをより堅牢にするためや、構造を管理するための変更が入っています。筆者はこれらの機能を取り込んだより使いやすい新しいフレームワークが出てくることのではないかと思っています。

 今回はPHP 7の新しい部分にフォーカスして紹介しましたが、次回は今回紹介できなかった機能や、PHP 5.xからの変更された仕様や、注意すべき点などを紹介します。

参考資料

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
PHP 7がやってきた!!連載記事一覧
この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 小林 昌弘(コバヤシ マサヒロ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/8951 2015/12/01 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング