日記

日々のことと、Python/Django/PHP/Laravel/nodejs などソフトウェア開発のことを書き綴ります

Laravel 5.1 入門記 その8(Views 編)

今回は Views です。

Views - Laravel - The PHP Framework For Web Artisans

Basic Usage

やっとテンプレートの話に突入。

コントローラからプレゼンテーションロジックを分離するために view を使います。 view は resources/views に配置します。では早速、サンプル通りのファイルを resource/views/greeting.php に作成します。

<html>
    <body>
        <h1>Hello, <?php echo $name; ?></h1>
    </body>
</html>

続いて、 routes.php に新しいルーティングを追加します。

Route::get('greeting', function ()    {
    return view('greeting', ['name' => 'James']);
});

そして、http://localhost:8080/greeting にアクセスすると

Hello, James

と表示されました\(^o^)/

return view('greeting', ['name' => 'James']);

この view 関数でテンプレート名と、テンプレートに渡すパラメータを定義してあります。テンプレート名は resources/views 以下の php ファイルを探しに行き、ディレクトリ階層がある場合は / では無く、ドットで区切って指定を行います。

もし view 全体にパラメータを設定して共有したいときは、AppServiceProvider の boot メソッドに定義を追加します。これも試してみます。 app/Providers/AppServiceProvider.php を次のように修正します。

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        view()->share('my_name', 'tnamao');
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

続いて、 resources/views/greeting.php を次のように編集します。

<html>
    <body>
        <h1>Hello, <?php echo $name; ?>. I'm <?php echo $my_name; ?></h1>
    </body>
</html>

そしてブラウザでアクセスすると…

Hello, James. I'm tnamao

共有パラメータも表示できました \(^o^)/

View Composers

View Composer は View の共通処理(例えばヘッダーとかに表示する情報やサイドバーの情報など)を一箇所にまとめて提議するためのものらしい。画面を Widget 的なもので構成するときに特に役に立つのかなと思った。

まずは簡単な、Closure での View Composer を定義してみます。app/Providers/ComposerServiceProvider.php を作成し、内容は以下の様にします。

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class ComposerServiceProvider extends ServiceProvider
{
    /**
     * コンテナ結合の登録
     *
     * @return void
     */
    public function boot()
    {
        // クロージャーベースのコンポーサーを使用する
        view()->composer('greeting', function ($view) {
            $view->with('composer_value', 'greeting composer!!');
        });
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

新しい Service Provider を作ったら app/config.php の providers に登録の必要があるため、 provides の配列に以下を追加します。

App\Providers\ComposerServiceProvider::class 

続いて、 resources/views/greeting.php に View Composer で設定した値を表示するコードを追記します。

<html>
    <body>
        <h1>Hello, <?php echo $name; ?>. I'm <?php echo $my_name; ?></h1>
        <p>compoer_value: <?php echo $composer_value; ?></p>
    </body>
</html>

そしてブラウザで http://localhost:8080/greeting にアクセスすると

Hello, James. I'm tnamao

compoer_value: greeting composer!!

\(^o^)/

View Composer は登録した時の第1引数で指定した値に一致する view が呼ばれた時にのみ実行されるようです。

view()->composer('greeting', function ($view) {

これですね。では、本当にそうなるのか、この greeting を残したまま、他の定義を ComposerServiceProvider に追加してみます。

view()->composer('hogehoge', function ($view) { $view->with('composer_value', 'hogehoge composer!!'); });

view()->composer('greeting', function ($view) { $view->with('composer_value', 'greeting composer!!'); });

変更後にブラウザでアクセスすると

Hello, James. I'm tnamao
compoer_value: greeting composer!!

と、無事に追加分の影響がありませんでした。ちなみに View Compoer が同じ View に複数定義されてしまった場合も見てみます。

view()->composer('greeting', function ($view) { $view->with('composer_value', 'greeting composer!!'); });

view()->composer('greeting', function ($view) { $view->with('composer_value', 'hogehoge composer!!'); });

前後を入れ替えて、どちらも view()->composer の第1引数を greeting にしてみました。これで表示を確認すると…

Hello, James. I'm tnamao
compoer_value: hogehoge composer!!

複数の View Composer を登録しても問題無いようで、登録した順番に実行されるので、同じ変数の場合は上書きされてしまうようです。

続いて View Composer を Closure ではなく、クラスに実装する方法です。View Composer を実装するクラスは、特に置く場所は決まっていないため、適当な場所に作ります。今回はドキュメントにならって、app/Http/ViewComposers/ProfileComposer.php に実装します。

<?php

namespace App\Http\ViewComposers;

use Illuminate\Contracts\View\View;

class ProfileComposer
{
    public function __construct()
    {
        // Dependencies automatically resolved by service container...
    }

    /**
     * Bind data to the view.
     *
     * @param  View  $view
     * @return void
     */
    public function compose(View $view)
    {
        $view->with('composer_value', 'class composer!!');
    }
}

実装したのは compose メソッド。続いて、ComposerServiceProvider にこのクラスを登録します。Closure で設定していたものは削除して、代わりに次の定義を追加しました。

view()->composer('greeting', 'App\Http\ViewComposers\ProfileComposer');

これで Closure と同じように登録完了です。ちなみに compose メソッドに実装を行いましたが、この composer に登録するときに @methodName とすれば、 compose メソッド以外でも登録可能です。

同一の View Composer 実装を複数の View に適用したいときは以下の様に 第1引数に array で対象の View 名を渡してあげれば適用されます。

view()->composer(['greeting1', 'greeting2'], 'App\Http\ViewComposers\ProfileComposer');

View Creators

View Creator はインスタンスが作られた直後に呼ばれるもので、View Composer のようにレンダリング時に実行されるものとは異なるらしい。

view()->creator('profile', 'App\Http\ViewCreators\ProfileCreator');

ComposerServiceProvider での登録はこんな感じで、create メソッドが呼ばれるらしい。恐らくメソッド名も変更可能なはず。試してないけど!

Views についてはここまで。次は Blade Templates やっとテンプレートエンジンの説明か〜 長かった。