Laravel4、パッケージがPHP5.3で動かない時

タグ: Laravel4  

あるパッケージのPHP要件が5.3以上になっているので、5.3環境で使えると思っても、エラーになる場合、本当は5.4以上が必要な場合が時々見受けられます。

例えばcomposer.jsonには以下のように書いてあります。

    "require": {
        "php": ">=5.3.0",
        "illuminate/support": "4.0.x"
    },

こう書かれると、packagistの表示もこれに基づいて表示されるため、5.3で動くと信じこんでしまいます。

もしコードの中に配列のショートカット記法が使ってあれば、明確にこの依存指定が間違っているとすぐ分かります。

return [ 'name' => 'Tonaka', 'age' => 87 ];

しかし、5.4の上で開発しておいて、5.3でも対応させようとこの記法を避けて書かれると、いきなりエラーでビビることもあるでしょう。

たいてい、クロージャーの中に$thisを持ち込んでいるのが原因です。私も、5.3で動くはずのコードが動かなかったり、サービスプロバーダーの中の定義がエラーになってしまっていたりで、首をひねりました。

よくあるのが、バインドのコードです。

$this->app->bind("chat.emitter", function()
{
    return new EventEmitter();
});

$this->app->bind("chat.chat", function()
{
    return new Chat(
         $this->app->make("chat.emitter")
    );
});

今訳している、リアルタイムチャットのコードです。:D サービスプロバーダーの中で結合している部分です。

これも、PHP 5.3以上と指定していますが、実際は5.4以上でないと動きません。(これ以外にも、たくさん[...]を使っているので、何が起きているか把握はしやすかったです。)5.3ではクロージャーの中に$thisを持ち込むとコンテキストがどうのこうのとFatalエラーになります。

5.3を使用している方で、サービスプロバイダー周りのIoC登録の部分が、参考にしている書籍やWebチュートリアル通りにやってもうまく動かなくて、悩んでいる方がいるかも知れませんね。

実際は、Laravelに組み込まれているサービスプロバイダーを参考にしてもらい、以下のように書くと5.3でも動作します。

$this->app->bind("chat.emitter", function()
{
    return new EventEmitter();
});

$this->app->bind("chat.chat", function($app)
{
    return new Chat(
         $app->make("chat.emitter")
    );
});

IoCコンテナでもあるAppクラスのインスタンスが、バインド時のクロージャーには渡されますので、それを利用して結合してください。