SHOEISHA iD

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

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

PHP 7がやってきた!!

PHP 5からPHP 7へ移行する際に気を付けるべきポイント

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

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

互換性がなくなるコード

 PHP 7になると、PHP 5.xまでと違って明らかに問題となるコードもあり、ある程度影響が大きいと思われる変更点を紹介します。また、ここで紹介するもの以外にもありますので、下記のドキュメントを参照してください。

基本型と同名のクラス宣言

 PHP 7では、新機能として関数や関数の引数に型宣言として基本型が使えるようになったり、新しい最上位のエラークラスとしてErrorクラスが追加されたりしました。PHP 7でこれらの基本型とクラス名がかぶる場合には問題となります。したがって、リスト3のようなstringクラスは作成ができなくなりました。ただし、厳密にはまだ、resource、object、mixed、numericなどは使えるようですが、これらも同様に使うべきクラス名ではないため、その利用は控える必要があります。

リスト3 基本型と同名のクラス(type/string.php)
class String{
}
$str = new String();

 あまり、stringといったクラスを定義するようなケースは実際の利用ではないとは思いますが、フレームワークなどではタイプヒンティングなどを基本型相当にも適用するなどの拡張を行うケースが考えられます。実際にCakePHP2.6まではstringクラスが存在(2.7でこれに対応)していたようです。

オブジェクトの作成時(new)での参照渡し

 オブジェクトを作成する際にnewで作成した値をそのまま参照渡しで変数に設定することは、PHP 4ではよくあるケースでした。PHP 5.xでは既に推奨されないコードでしたが、PHP 7ではエラーになるようになりましたので、リスト4のようなコードは記述できなくなります。

リスト4 new時の参照渡し(refnew.php)
class Foo{}
$foo =& new Foo();

変数の取り扱いの変更

 可変変数での配列やプロパティにアクセスする場合の評価する順番が、PHP 5.xとPHP 7で変わました。

 単純な変数表記であれば、PHP 5.xとPHP 7で問題となることはありませんが、配列を使った配列の参照やオブジェクト、メソッド参照を行っている場合に特に注意が必要になります。

表1 評価の違い
PHP 5での解釈 PHP 7での解釈
$$name['key']['value'] ${$name['key']['value']} ($$name)['key']['value']
$name->$key['value'] $name->{$key['value']} ($name->$key)['value']
$name->$key['value']() $name->{$key['value']}() ($name->$key)['value']()
Person::$key['value']() Person::{$key['value']}() (Person::$name)['value']()

 これらで実際に問題となるコードがリスト5のようになります。

リスト5 解釈の違いでエラーになるコード例(vars/parse.php)
class Person{
    function hello(){
        echo "Hello\n";
    }
}
$name = array(
    'key' => array('value' => 'kobayashi' , 'method' => 'hello')
);
$kobayashi = new Person();

var_dump($$name['key']['value']);  //(1)
var_dump(${$name['key']['value']});  //(2)

$kobayashi->$name['key']['method'](); //(3)
$kobayashi->{$name['key']['method']}(); //(4)

 (1)では、実際には$kobayashiという変数を想定したコードですが、$$nameが先に解釈されるためにPHP 7では結果としてエラーとなります。したがって、(2)のようにしなければPHP 5でもPHP 7でも同じような動作にはなりません。

 また、(3)は$kobayashi->hello()というコードを想定したものですが、PHP 7では$kobayashi->$nameが先に解釈されるためにエラーとなります。こちらも、同じようにPHP 7でも動作するようにするためには(4)のようにする必要があります。

 また、関数内などでスコープ外の変数を扱うglobalでは、{}を使用しない可変変数自体の利用が禁止されました。

 もともと、global自体推奨される機能ではありませんが、上記のような評価順が変わることにより、結果的にglobalで不明瞭な変数を指す可能性があることから、明示的な利用しか許可しないことはやむを得ないとも思います。

 このように、PHP 7ではこのような変数を用いた変数の参照では、{}を使って明示的な評価順を記述するようにしましょう。

参照渡し時のforeachでの処理の違い

 foreach内で大きなオブジェクトを扱う場合などでよく参照渡しによる処理をするケースがありますが、参照渡しでのforeachでは振る舞いが変わっていますので注意が必要になります。この振る舞いの違いによって結果の違いが発生するようなコードがリスト6のようになります。

リスト6 参照渡しによるforeachによる影響(foreach.php)
$prefs = ["hokkaido","tokyo"];

//(1)foreach内でのcurrentの扱い方
foreach($prefs as &$name){
    echo $name." --> next: ";
    echo current($prefs) ."\n";
}

//(2)foreach内でのリストの変更
foreach($prefs as &$name){
    if($name == 'tokyo'){
        $prefs[] = "shibuya";
        $prefs[] = "shinjyuku";
    }
    var_dump($name);
}

 リスト6をPHP 5.xとPHP 7で実行した結果ではリスト7のように違いが生じます。

リスト7 リストXXの実行結果
// PHP 5.xの実行結果
hokkaido --> next: tokyo
tokyo --> next:
string(8) "hokkaido"
string(5) "tokyo"

// PHP 7の実行結果
hokkaido --> next: hokkaido
tokyo --> next: hokkaido
string(8) "hokkaido"
string(5) "tokyo"
string(7) "shibuya"
string(9) "shinjyuku"

 foreach内のでcurrent()関数の扱いが代わり、PHP 5.xではforeach内で配列ポインタを移動していたので、current()関数で次の値を取得できましたが、PHP 7では配列ポインタを移動しないために、foreach内でcurrent()関数を使っても常に配列の最初の要素を示すようになります。

 また、PHP 5.xではforeach内でリスト自体に要素を追加しても、foreachで繰り返されるのはforeach処理がされる前のリストでしたが、PHP 7ではforeach内でリストを追加するとその要素も繰り返し処理がされることになりました。

 繰り返し処理内でそのリスト自身に変更を加えることはよくあるケースと思われるために、参照渡しでforeachを利用している場合には注意が必要です。ただし、参照渡しではない場合には、このようなforeach内でのリスト変更においてもPHP 5と同様の結果になります。

次のページ
削除された関数

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

  • 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/8952 2016/02/05 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング