Laravel 5 チュートリアル - Routing

アプリケーションを構成する、基本的なページが表示できるようにします。

Routingのキソ

ルートはapp/Http/routes.phpにまとめて定義します。プロジェクト作成時は以下の様に定義されています。/へのリクエストにwelcomeビューを返すというような処理なのが、なんとなく分かります。

Route::get('/', function () {  
    return view('welcome');
});

view()の引数にはViewファイル名を渡します。Viewファイルはresources/viewsにあるものを使用してくれるので、resources/views/welcome.blade.phpを返しています。*.blade.phpはLaravelで使用されているBladeというテンプレートエンジンです。

基本的にはRoute::[HTTPの動詞]にURIとハンドラとなるクロージャを渡します。

Route::get('/', function() {  
    return 'get /';
});

Route::post('/', function() {  
    return 'post /';
});

Route::put('/', function() {  
    return 'put /';
});

Route::delete('/', function() {  
    return 'delete /';
});

パラメータを取る場合は{}で囲みます。

Route::get('tasks/{id}', function($id) {  
    return 'get /tasks/'.$id;
});

/tasks/10のようなURIに対応しますが、このままだと数値でも文字列でも有効になってしまいます。パラメータの方を制限したい場合には正規表現を使います。

Route::get('tasks/{id}', function($id) {  
    return 'get /tasks/'.$id;
})->where('id', '[0-9]+');

// /tasks/hoge
//-> NotFoundHttpException

// /tasks/10
//-> get /tasks/10

Viewを返す

HTMLテンプレートにデータを埋め込んでページを返します。

Route::get('tasks', function() {  
    $tasks = [
        ['id'=> 1, 'task'=>'task 1'],
        ['id'=> 2, 'task'=>'task 2']
    ];
    return view('tasks.index')->with('tasks', $tasks);
});

view()に渡すテンプレートファイルは.で区切るとtasks/index.blade.phpを指します。->with()でViewに渡す変数名と変数を指定しますが、複数のデータを渡すとなると->with()を連続で呼ばなければなりません。その場合はcompactを使うとすっきりします。

Route::get('tasks', function() {  
    $tasks = [
        ['id'=> 1, 'task'=>'task 1'],
        ['id'=> 2, 'task'=>'task 2']
    ];
    $foo = 'foo';
    $bar = 'bar';

    return view('tasks.index', compact(
        'tasks',
        'foo',
        'bar'
    ));
});

テンプレート側では、それぞれ$tasks/$foo/$barのように参照します。

View

LaravelではテンプレートエンジンにBladeを使っています。レイアウト、パーシャル、変数の表示、制御構造辺りを押さえておきます。

Layout

ベースとなるビューを作り、各ページでレイアウトを拡張することができます。resources/views/layoutsディレクトリにレイアウトを作ります。

<!-- resources/views/layouts/master.blade.php -->  
<!DOCTYPE html>  
<html>  
<head>  
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>@yield('title') | Hello Laravel</title>
</head>  
<body>  
  @include('shared.header')
  @yield('content')
  @include('shared.footer')
</body>  
</html>  

@includeディレクティブでサブビューのインクルードをします。@yieldはレイアウトを拡張するテンプレート側でコンテンツのプレースホルダーの様になります。テンプレート側では@yieldで定義されているセクションに@sectionディレクティブを使ってコンテンツを記述することになります。

@extends('layouts.master')

@section('title', 'Tasks')

@section('content')
<ul>  
  {{ $foo }}
  {{ $bar }}
  @foreach($tasks as $task)
  <li>{{ $task['task'] }}</li>
  @endforeach
</ul>  
@endsection

レイアウトを拡張する側で、レイアウトの@yieldのコンテンツを定義しなければ、その部分は何も表示されないだけです。

また、レイアウトに@sectionを定義することもできます。

<!DOCTYPE html>  
<html>  
<head>  
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>@yield('title') | Hello Laravel</title>
</head>  
<body>  
  @section('header')
  <div>this is header</div>
  @show

  @yield('content')
</body>  
</html>  

@section ~ @show間のコンテンツは拡張するテンプレート側で対応する@section ~ @sectionendがあれば置き換わります。無ければレイアウトの@section ~ @show間のコンテンツが表示されるようになります。

@extends('layouts.master')

// ...

@section('header')
alternative header!  
@endsection

レイアウトの@section('header')を表示しつつ、テンプレート側で独自にコンテンツを追加したい場合は@parentディレクティブを使用します。

@extends('layouts.master')

// ...

@section('header')
  @parent

  <small>appended by child template</small>
@endsection

テンプレート内ではコントローラから受け取った変数を表示する際{{ $hoge }}のような記述になります。デフォルトでhtmlentities関数の返り値が表示されるようになります。エスケープしたくない場合は{{!! $hoge !!}}にします。

制御構造は他のテンプレートエンジンでもよく見るものが用意されているので省略します。

Blade - Control Structure ドキュメント

Controller

これまではクロージャベースのルーティングを定義しましたが、LaravelではコントローラーとしてURIに対応するロジックを定義することもできます。

コントローラーはapp/Http/Controllers以下にapp/Http/Controllers/Controller.phpを継承したクラスファイルとして作ります。

// app/Http/Controllers/TaskController.php

namespace HelloLaravel\Http\Controllers;

class TaskController extends Controller {  
    public function show()
    {
        $tasks = [
            ['id'=> 1, 'task'=>'task 1'],
            ['id'=> 2, 'task'=>'task 2']
        ];
        $foo = 'foo';
        $bar = 'bar';
        return view('tasks.index', compact(
            'tasks',
            'foo',
            'bar'
        ));
    }
}

app/Http/routes.phpでは、URIに対してコントローラクラス@アクションメソッドを指定します。

Route::get('tasks', 'TaskController@show');