速習Larave3(その2)、レコードの追加と一覧表示

タグ: Laravel3  

今回は、レコードを追加します。そのため、フォームでユーザーから入力してもらいましょう。

ソース:github

更に、記事の一覧も表示します。記事の表示、追加、一覧とビューが増えますので、その共通部分をレイアウト(共通テンプレート)として独立させます。そのほうが実用的ですからね。

まずはルートから考えましょう。作成するのはブログです。すると、トップページでは記事の一覧が表示されるのが便利です。読者は読みたい記事を選べますからね。

中にはあなたのブログのファンになり、何度もやってきてくれる方もいるでしょう。あなたのファンのために、新しい記事を最初に表示しましょう。そうすれば、ひと目で新記事を見つけてもらえます。

まず、各ページにアクセスするためのURIを決めましょう。

機能 URI
一覧表示 /
記事表示 /post/記事番号
記事追加 /post/add

URIはあなたのサイトへアクセスする場合のドメイン以降に指定するアドレスです。

ではこれに従い、application/routes.phpを設定しましょう。ルートルートRoute::get('/',...の定義は書き換えてください。記事表示と記事追加のルートは追加します。それ以外の部分は前回と同じですので、変更しないでください。

/*
 * 一覧表示
 */

Route::get('/',
    array( 'as' => 'post-index', function() {
        $posts = Post::order_by('created_at', 'desc')->get();
        return view('post.index')
                ->with('posts', $posts);
    } ));

/*
 * 記事表示
 */

Route::get('/post/(:num)',
    array( 'as' => 'post-show',
    function($id) {
        $post = Post::find($id);

        if ( $post === null )
        {
            return Redirect::error('404');
        }

        return View::make('post.show')
                ->with('title', $post->title)
                ->with('body', $post->body);
    } ));

/*
 * 記事追加
 */

// フォーム表示
Route::get('/post/add', array( 'as' => 'post-add', function() {
        return view('post.add');
    } ));

// フォーム処理
Route::post('/post/add',
    array( 'as' => 'post-add',
    function() {
        $input = Input::only(array( 'title', 'body' ));

        $post = new Post($input);
        $post->save();

        return Redirect::to_route('post-add');
    } ));

ルーティングにはasで名前をつけています。これは後ほどこのルートにリンクを張る場合に便利になります。

一覧表示はPostクラスを作成日付でソートし、get()メソッドで内容を取得しています。get()で取得した場合、Postクラスの配列が返ってきます。

記事の表示は前回とほぼ同じです。ルートの定義で/post/show/の後に数字が指定された場合、このルートに制御が渡り、$idにはURIで指定された数字が代入されます。find()はレコードのidを指定し、存在すればそのクラスのインスタンスを返します。存在しない場合はnullを返します。それをチェックし、存在しないポストのidを指定された場合は404エラーページを表示します。

フォームの処理はHTTPメソッドがGETの場合は、フォームの表示だけを行い、フォームを送信された場合のPOSTでは、その処理だけを行います。処理を分けることでそれぞれが単純になります。ORMはクラスでテーブル操作を行う手法です。ですから、新しいレコード追加とは、新しいクラスを作成することです。Input::only()でレコード追加に必要なフィールドのみ取得し、その内容で新しいクラスを作成し、save()で実際に保存します。

最後に自分自身につけたルート名add-postを指定しリダイレクトすることで、post/addをGETメソッドで呼び出すことになり、再度フォームが表示されます。今回はフォームに何も渡していないため、空白ページが表示されます。

続いてビューへ移りましょう。

前回のビューをよく見てみると、他のビューでも共通して使用できる部分が多いことに気が付きます。その部分は共通で使いまわしましょう。一般的にはテンプレートと呼ばれることが多いですがビューの共通部分、Laravelの呼び方では「レイアウト」として利用します。application/views/template.blade.phpを作成してください。

参照:テンプレート

<!doctype html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>@yield('title')</title>
    <meta name="viewport" content="width=device-width">
    {{ HTML::style('laravel/css/style.css') }}
</head>
<body>
    <div class="wrapper">
        <header>
            <h1>ミニブログ</h1>
            <h2>@yield('title')</h2>
            <p class="intro-text" style="margin-top: 45px;">
            </p>
        </header>
        <div role="main" class="main">
            <div class="home">
                @yield('content')
            </div>
        </div>
    </div>
</body>
</html>

@yieldはLaravelの細かい表示単位、セクションをその位置に読み込むことを指定しています。titleセクションを2箇所、contentセクションを一箇所で読み込んでいます。

セクションはテンプレートだけではよく分かりません。それを呼び出すビューを一緒にご覧ください。application/views/index.blade.phpです。一覧表示のビューです。

@layout('template')

@section('title')
    一覧表示
@endsection

@section('content')
    <table>
        <tr>
            <th>タイトル</th>
            <th>作成日</th>
        </tr>
        @foreach($posts as $post)
            <tr>
                <td>{{ HTML::link_to_route('post-show', $post->title ,array($post->id)) }}</td>
                <td>{{ $post->created_at }}</td>
            </tr>
        @endforeach
    </table>
@endsection

@layoutでレイアウトを指定します。@sectionから@endsectionまでが、一つのセクションです。

同様にapplication/views/show.blade.viewも見てみましょう。前回のビューとほぼ同じです。変更してください。

@layout('template')

@section('title')
    ポスト表示
@endsection

@section('content')
    <h2>{{ e($title) }}</h2>
    {{ e($body) }}
@endsection

共通部分を抜き出してしまっているので、スカスカです。セクション名のtitleと記事のタイトルが渡される$titleが多少ややこしいですが、混同しないでください。

e()ヘルパーで出力内容をエスケープします。XSS対策です。HTMLクラス、Formクラスを通し表示する場合は内部でe()を自動的に通してくれます。自前でユーザーが入力したデーターを出力する場合は必ずこのヘルパーを通しましょう。

次に追加フォームのビューです。application/views/add.blade.phpです。

@layout('template')

@section('title')
    記事追加
@endsection

@section('content')
    {{ Form::open() }}
        <div>
            {{ Form::label('title', 'タイトル') }}<br>
            {{ Form::text('title', Input::old('title', '')) }}
        </div>
        <div>
            {{ Form::label('body', '本文') }}<br>
            {{ Form::textarea('body', Input::old('body', '')) }}
        </div>
        <div>
            {{ Form::submit('送信') }}
        </div>
    {{ Form::close() }}
@endsection

参照:フォームの作成

さあ、これで記事の追加ができます。URI/post/addでアクセスし、記事を追加してください。ルート(トップ)ルートで一覧ページを表示し、記事が追加されていることを確認してください。

今の時点ではどんなタイトル、どんな記事の内容も追加できます。実際にどんどん追加しましょう。