Written by Manabu Bannai

Laravelでブログを作成する方法【チュートリアル】

Laravel PROGRAMMING

Laravelの勉強として、ブログを作成したので、その方法をまとめました。以下の英語記事を参考に作成し、いくつかバグのあるコードを修正しました。
» Creating a Blog Using Laravel 4 Part 1: Models and Seeding – CodeHeaps

類似記事も書いています。以下の記事のほうが難易度が低いです。
» 【保存版】Laravelで掲示板を作成する方法【チュートリアル】

記事の対象者

  • PHPの基礎がわかる人
  • Laravelの基本がわかる人
  • やる気がある人

ブログの機能一覧

  • 記事一覧の表示
  • 続きを読むボタンの表示
  • 記事の検索機能
  • コメント機能
  • ログイン機能
  • 会員登録機能
  • ユーザーは自分の記事のCRUD処理ができる
  • 会員はコメントの承認/非承認を選択できる

もくじ

それでは、まとめていきます( ◜◡‾)

【1】LaravelのDBセットアップ

DBのセットアップ

編集ファイル:app/config/database.php


'mysql' => array(
  'driver'    => 'mysql',
  'host'      => 'localhost',
  'database'  => 'classified',
  'username'  => 'root',
  'password'  => 'root',
  'charset'   => 'utf8',
  'collation' => 'utf8_unicode_ci',
  'prefix'    => '',
),

【2】Laravelのマイグレーション

postsテーブルのマイグレーション


$ php artisan migrate:make create_posts_table
Created Migration: 2014_10_09_142812_create_posts_table
Generating optimized class loader
Compiling common classes
Compiling views

生成されたファイルに以下を記述します。


<?php

use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;

class CreatePostsTable extends Migration {

  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up()
  {
    Schema::create('posts', function($table){
      $table->increments('id');
      $table->unsignedInteger('author_id');
      $table->string('title');
      $table->string('read_more');
      $table->text('content');
      $table->unsignedInteger('comment_count');
      $table->timestamps();
      $table->engine = 'MyISAM';
    });
  }

  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down()
  {
    Schema::drop('posts');
  }

}

解説:$table->engine=’MyISAM’

上記はMySQLの検索機能を利用するために設定しています。

その後、マイグレートします。


$ php artisan migrate

commentsテーブルのマイグレーション


$ php artisan migrate:make create_comments_table
Created Migration: 2014_10_09_143901_create_comments_table
Generating optimized class loader
Compiling common classes
Compiling views

生成されたファイルに以下を記述します。


<?php

use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;

class CreateCommentsTable extends Migration {

  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up()
  {
    Schema::create('comments', function($table){
      $table->increments('id');
      $table->unsignedInteger('post_id');
      $table->string('commenter');
      $table->string('email');
      $table->text('comment');
      $table->boolean('approved');
      $table->timestamps();
    });
  }

  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down()
  {
    Schema::drop('comments');
  }

}

解説:post_id

post_idはcommmentsテーブルとpostsテーブルを紐づけます。
また、approvedフィールドでは、あとで解説するusersテーブルと連携します。
その後、マイグレートをします。


$ php artisan migrate

【3】Eloquent ORMを使ったモデル作成

Eloquent ORMでモデルを作成する

規約に従うため、モデル名は『テーブル名の単数形』を使います。
それでは、Postモデルを作っていきます。

新規作成ファイル:app/models/Post.php


<?php
class Post extends Eloquent{

  protected $fillable = ['title', 'content'];

  public function comments(){
    return $this->hasMany('Comment');
  }

  public function user(){
    return $this->belongsTo('User');
  }

}

つぎにCommentモデルを作成します。
新規作成ファイル:app/models/Comment.php


<?php
class Comment extends Eloquent{

  protected $fillable = ['commenter', 'email', 'comment'];

  public function post(){
    return $this->belongsTo('Post');
  }

  public function getApprovedAttribute($approved){
    return (intval($approved) == 1) ? 'yes' : 'no';
  }

  public function setApprovedAttribute($approved){
    $this->attributes['approved'] = ($approved === 'yes') ? 1 : 0;
  }

}

【4】データベースにダミーデータの送信

シードコマンドでDBにダミーデータを送信する

artisan db:seedというコマンドでDBにダミーデータを挿入することができます。
まずは、PostCommentSeederを以下のとおりに作成します。
新規作成ファイル:app/database/seeds/PostCommentSeeder.php


<?php

class PostCommentSeeder extends Seeder{

public function run(){
  $content = 'この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。';

  for( $i = 1 ; $i <= 20 ; $i++) {
    $post = new Post;
    $post->title = "$i 番目の投稿";
    $post->author_id = 1;
    $post->read_more = substr($content, 0, 120);
    $post->content = $content;
    $post->save();

    $maxComments = mt_rand(3, 15);
    for ($j=0; $j <= $maxComments; $j++) {
      $comment = new Comment;
      $comment->commenter = '名無し';
      $comment->comment = substr($content, 0, 120);
      $comment->email = '[email protected]';
      $comment->approved = 1;
      $post->comments()->save($comment);
      $post->increment('comment_count');
    }
  }
}
}

以下のコマンドで実行します。
php artisan db:seed --class= PostCommentSeeder

※注意
php artisan db:seedだと、デフォルトのシード(DatabaseSeeder.php)が実行されてしまいます。

【5】各種コントローラーの作成

BlogControllerを作成する

BlogControllerでは、主に以下の処理を行ないます。

  • トップページの保存
  • 記事の検索
  • 検索結果の表示
  • ユーザーログイン/ログアウト

尚、記事とコメントのCRUD処理はPostControllerとCommentControllerで処理します。それでは、BlogControllerをつくっていきます( ◜◡‾)

新規作成ファイル:app/controllers/BlogController.php


<?php

class BlogController extends BaseController{

public function __construct(){
  // 再度ログインすることを防ぐ処理
  $this->beforeFilter('guest', ['only' => ['getLogin']]);
  $this->beforeFilter('auth', ['only' => ['getLogout']]);
}

public function getIndex(){
  $posts = Post::orderBy('id', 'desc')->paginate(10);

  $posts->getFactory()->setViewName('pagination::simple');
  $this->layout->title = 'Laravelでブログ作成';
  $this->layout->main = View::make('home')->nest('content', 'index', compact('posts'));

}

public function getSearch(){
  $searchTerm = Input::get('s');
  $posts = Post::where('title', 'LIKE', '%'.$searchTerm.'%')->paginate(10);
  $posts->getFactory()->setViewName('pagination::slider');
  $posts->appends(['s'=>$searchTerm]);
  $this->layout->with('title', '検索:'.$searchTerm);
  $this->layout->main = View::make('home')->nest('content', 'index', ($posts->isEmpty()) ? ['notFound'=>true] : compact('posts'));
}

public function getLogin(){
  $this->layout->title = 'login';
  $this->layout->main = View::make('login');
}

public function postLogin(){
  $credentials = [
    'username'=>Input::get('username'),
    'password'=>Input::get('password')
  ];

  $rules = [
    'username'=>'required',
    'password'=>'required'
  ];

  $validator = Validator::make($credentials, $rules);
  if ($validator->passes()) {

    if (Auth::attempt($credentials)) {
      return Redirect::to('admin/dash-board');
    }else{
      return Redirect::back()->withInput()->with('failure', '正しいユーザー名/パスワードを入力してください。');
    }

  }else{
    return Redirect::back()->withErrors($validator)->withInput();
  }
}

public function getLogout(){
  Auth::logout();
  return Redirect::to('/');
}

}

getIndexファンクションに関して

Postモデルを利用してクエリを行ないます。
同時に、Paginatorを使い1ページに10件の投稿を表示しています。

getSearchファンクションに関して

検索キーワード(searchTerms)に応じて、ポストモデルからクエリを行ないます。
検索結果の1ページ目はpaginateに紐づきますが、それ以外のページは$post->appendsによって、情報の紐付けを行なっています。

nestに関して

使い方は以下です。
nest(partial viewの名前, viewへのパス, 送信したいデータ)

compactに関して

参考:PHP関数「compact」と「extract」を試してみる

PostControllerを作成する

新規作成ファイル:app/controllers/PostController.php


<?php

class PostController extends BaseController{

public function listPost(){
  // AuthユーザーIDを取得する
  $id = Auth::user()->id;

  // ユーザーIDとauthorIDの等しい記事を取得する
  $posts = Post::where('author_id', '=', $id)->get();

  // $posts = Post::orderBy('id', 'desc')->paginate(10);
  $this->layout->title = '記事一覧';
  $this->layout->main = View::make('dash')->nest('content', 'posts.list', compact('posts'));
}

// ※ルートとモデルの結合:解説あり
public function showPost(Post $post){
  $comments = $post->comments()->where('approved', '=', 1)->get();
  $this->layout->title = $post->title;

  // nestを使うことで、homeビューの中にindexビューを埋込みます
  $this->layout->main = View::make('home')->nest('content', 'posts.single', compact('post', 'comments'));
}

public function newPost(){
  $this->layout->title = '新規投稿';
  $this->layout->main = View::make('dash')->nest('content', 'posts.new');
}

public function editPost(Post $post){
  $this->layout->title = '記事の編集';
  $this->layout->main = View::make('dash')->nest('content', 'posts.edit', compact('post'));
}

public function deletePost(Post $post){
  $post->delete();
  return Redirect::route('post.list') ->with('success', '記事が削除されました');
}

public function savePost(){
  $post = [
    'title' => Input::get('title'),
    'content' => Input::get('content'),
  ];

  $rules = [
    'title' => 'required',
    'content' => 'required',
  ];

  $valid = Validator::make($post, $rules);
  if ($valid->passes()) {
    $post = new Post($post);
    $post->author_id = Auth::user()->id;
    $post->comment_count = 0;
    $post->read_more = (strlen($post->content) > 120) ? sbstr($post->content, 0, 120) : $post->content;
    $post->save();
    return Redirect::to('admin/dash-board')->with('success', '投稿が保存されました');
  }else{
    return Redirect::back()->withErrors($valid)->withInput();
  }
}

public function updatePost(Post $post){
  $data = [
    'title' => Input::get('title'),
    'content' => Input::get('content'),
  ];

  $rules = [
    'title' => 'required',
    'content' => 'required',
  ];
  $valid = Validator::make($data, $rules);
  if ($valid->passes()) {
    $post->title = $data['title'];
    $post->content = $data['content'];
    $post->read_more = (strlen($post->content) > 120) ? sbstr($post->content, 0, 120) : $post->content;

    // 同じ投稿を再度送信することを避ける
    // getDirty:Get the attributes that have been changed since last sync.
    if (count($post->getDirty()) > 0) {
      $post->save();
      return Redirect::back()->with('success', '投稿が更新されました');
    }else{
      return Redirect::back()->with('success', '更新内容がありません');
    }

  }else{
    return Redirect::back()->withErrors($valid)->withInput();
  }

}

}

ルートとモデルの結合に関して解説します。
たとえば、以下のプログラムをご覧ください。


<?php
//ファイル場所:app/routes.php
 
Route::model('post', 'Post'); 
 
Route::get('post/{post}',function(Post $post)
{
    echo $post->title;
 
});

このプログラム書いた上で、postIDを渡してルートにアクセスします。
すると、Postモデルが自動的にIDに対応した情報をもってきてくれます。
Laravelの便利な機能のうちのひとつです( ◜◡‾)

次のステップへ進みます。

CommentControllerを作成する

新規作成ファイル:app/controller/CommentController.php


<?php

class CommentController extends BaseController{

public function listComment(){
  $comments = Comment::orderBy('id', 'desc')->paginate(20);
  $this->layout->title = 'コメント一覧';
  $this->layout->main = View::make('dash')->nest('content', 'comments.list', compact('comments'));
}

public function newComment(Post $post){
  $comment = [
    'commenter' => Input::get('commenter'),
    'email' => Input::get('email'),
    'comment' => Input::get('comment'),
  ];
  $rules = [
    'commenter' => 'required',
    'email' => 'required|email',
    'comment' => 'required',
  ];

  $valid = Validator::make($comment, $rules);
  if ($valid->passes()) {
    $comment = new Comment($comment);
    $comment->approved = 'no';
    $post->comments()->save($comment);

    return Redirect::to(URL::previous().'#reply')->with('success', 'コメントが送信されました。現在は承認待ちです。');
  }else{
    return Redirect::to(URL::previous().'#reply')->withErrors($valid)->withInput();
  }
}

public function showComment(Comment $comment){
  if (Request::ajax()) {
    return View::make('comments.show', compact('comment'));
  }
}

public function deleteComment(Comment $comment){
  $post = $comment->post;
  $status = $comment->approved;
  $comment->delete();
  ($status === 'yes') ? $post->decrement('comment_count') : '';
  return Redirect::back()->with('success', 'コメントが削除されました');
}

public function updateComment(Comment $comment){
  $comment->approved = Input::get('status');
  $comment->save();
  $comment->post->comment_count = Comment::where('post_id', '=', $comment->post->id)->where('approved', '=', 1)->count();
  $comment->post->save();
  return Redirect::back()->with('success', 'Comment'. (($comment->approved === 'yes') ? 'Approved' : 'Disapproved'));
}

}

ここまでで、以下が完了しました。

  • Laravelの初期セットアップ
  • Laravelのマイグレーション
  • Eloquent ORMを使ったモデル作成
  • データベースにダミーデータの送信
  • 各種コントローラーの作成

【6】ルーティングの設定

つぎはルーティングを作っていきます。ルーティングを作成する前に、さらっと基礎を復習します。以下をご覧ください。


<?php
 
// GETリクエストはつぎのように処理します
Route::get('index',function(){
    echo 'これが index pageです';
});
 
Route::get('login',function(){
    echo 'これがログインぺーじです.';
});
 
// POSTリクエストはつぎのように処理します。
Route::post('login', function() {
    echo 'POSTリクエストです';
});

コントローラーのリクエストは次のように行ないます。


Route::get('users', 'UsersController@getIndex');

上記のように記述した場合、 /users へのすべてのリクエストがUserControllerのgetIndexファンクションで処理されます。

ルーターでパラメータを渡すには以下のように記述します。


<?php
 
// パラメータ{id}がわたされます
Route::any('post/{id}',function($id){
    echo "$id がわたされています。";
});
 
// ルートとモデルの結合
Route::model('post','Post'); // {post}でわたされたパラメータがPostモデルで処理されます
binds a model to the route parameter {post}
 

以上で、基本的な処理の解説はおわりです。
あわせて以下の記事をご覧いただくと、理解が深まります。
» 【アメリカで人気なPHPフレームワーク】Laravelの使い方メモ

それでは、開発を進めていきましょう。

ブログのルーターを作成する

編集ファイル:app/routes.php


<?php

// モデルとの結合
Route::model('post', 'Post');
Route::model('comment', 'Comment');
Route::model('user', 'User');

// ユーザーのルート設定
Route::get('/post/{post}/show', ['as' => 'post.show', 'uses' => 'PostController@showPost']);
Route::post('/post/{post}/comment', ['as' => 'comment.new', 'uses' => 'CommentController@newComment']);

// アドミンのルート設定
Route::group(['prefix' => 'admin', 'before' => 'auth'], function(){

  // ルートの取得
  Route::get('dash-board', function(){
    $layout = View::make('master');
    $layout->title = '管理パネル';
    $layout->main = View::make('dash')->with('content', '管理パネルへようこそ<(_ _)>');
    return $layout;
  });

  Route::get('/post/list', ['as' => 'post.list', 'uses' => 'PostController@listPost']);
  Route::get('/post/new', ['as' => 'post.new', 'uses' => 'PostController@newPost']);

  Route::get('/post/{post}/edit', ['as' => 'post.edit', 'uses' => 'PostController@editPost']);
  Route::get('/post/{post}/delete', ['as' => 'post.delete', 'uses' => 'PostController@deletePost']);

  Route::get('/comment/list', ['as' => 'comment.list', 'uses' => 'CommentController@listComment']);
  Route::get('/comment/{comment}/show', ['as' => 'comment.show', 'uses' => 'CommentController@showComment']);
  Route::get('/comment/{comment}/delete', ['as' => 'comment.delete', 'uses' => 'CommentController@deleteComment']);

  // 投稿のルート設定
  Route::post('/post/save', ['as' => 'post.save', 'uses' => 'PostController@savePost']);
  Route::post('/post/{post}/update', ['as' => 'post.update', 'uses' => 'PostController@updatePost']);
  Route::post('/comment/{comment}/update', ['as' => 'comment.update', 'uses' => 'CommentController@updateComment']);

});

// ホームのルート設定
Route::controller('/', 'BlogController');

// ビューコンポーサー
// サイドバーに最近の投稿を表示するためのルーティング
View::composer('sidebar', function ($view) {
    $view->recentPosts = Post::orderBy('id', 'desc')->take(5)->get();
});

【7】ユーザー認証

AdminのルートをAuthenticationで保護する

Laravelには、『auth』『guest』認証が含まれています。

authとは
ユーザーがログインしている場合はTrueを返す

guestとは
ユーザーがログインしていない場合はTrueを返す

今回作成したルートプログラムにはauthファンクションを利用していることがわかるかと思います。
それでは、ユーザー認証をつくっていきます。

マイグレーションする

以下のコマンドを実行します。


$ php artisan migrate:make create_users_table --table='users'
Created Migration: 2014_10_11_072228_create_users_table
Generating optimized class loader

作成されたファイルを以下のように編集します。
編集ファイル:app/database/misrations/[実行日] create_users_table.php


<?php

use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;

class CreateUsersTable extends Migration {

  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up()
  {
    Schema::table('users', function(Blueprint $table)
    {
      $table->create();
      $table->increments('id');
      $table->string('username');
      $table->string('password');
      $table->string('email');
      $table->string('photo');
      $table->string('remember_token')->nullable();
      $table->timestamps();
    });
  }

  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down()
  {
    Schema::table('users', function(Blueprint $table)
    {
      Schema::drop('users');
    });
  }

}

その後、マイグレートします。

$ php artisan migrate

これで、usersテーブルが完成しました。

ユーザーのダミーデータを生成する

ブログのコンテンツ/コメントを生成した方法とほぼ同じです。
編集ファイル:app/database/seeds/DatbaseSeeder.php
上記ファイルを以下のように変更します。


<?php

class DatabaseSeeder extends Seeder {

  /**
   * Run the database seeds.
   *
   * @return void
   */
  public function run()
  {
    Eloquent::unguard();
    $this->call('UserTableSeeder');
  }

}

つぎに、UserTableSeederを作成します。
新規作成ファイル:app/database/seeds/UserTableSeeder.php


<?php

class UserTableSeeder extends Seeder {

  public function run()
  {
    $user = array(
      'username' => 'hogehoge',
      'password' => Hash::make('admin'),
      'created_at' => DB::raw('NOW()'),
      'updated_at' => DB::raw('NOW()'),
      );

     DB::table('users')->insert($user);
  }

}

上記ファイルを実行します。

$ php artisan db:seed

usersテーブルに新規のユーザーが追加されたかと思います。
加えて、Userモデルを以下のように編集します。
編集ファイル:app/models/User.php


<?php

use IlluminateAuthUserTrait;
use IlluminateAuthUserInterface;
use IlluminateAuthRemindersRemindableTrait;
use IlluminateAuthRemindersRemindableInterface;

class User extends Eloquent implements UserInterface, RemindableInterface {

  use UserTrait, RemindableTrait;

  /**
   * The database table used by the model.
   *
   * @var string
   */
  protected $table = 'users';

  /**
   * The attributes excluded from the model's JSON form.
   *
   * @var array
   */
  protected $hidden = array('password', 'remember_token');
  protected $fillable = array('username', 'email');

  public function posts(){
    return $this->hasMany('Post');
  }

}

ここまでで、以下が完了しました。

  • Laravelの初期セットアップ
  • Laravelのマイグレーション
  • Eloquent ORMを使ったモデル作成
  • データベースにダミーデータの送信
  • 各種コントローラーの作成
  • ルーティングの設定
  • ユーザー認証

つぎはビューを作っていきます。

【8】ビューの作成

マスターのレイアウトの作成

新規作成ファイル:app/views/master.blade.php


<!DOCTYPE html>
<html class="no-js" lang="ja">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  @section('title')
    <title>{{{$title}}}</title>
  @show
  {{ HTML::style('assets/css/foundation.css') }}
  {{ HTML::style('assets/css/custom.css') }}
  {{ HTML::script('./assets/js/vendor/custom.modernizr.js') }}
</head>
<body>
<div class="row main">
  <div class="small-12 large-12 column" id="masthead">
    <header>
      <nav class="top-bar" data-topbar>
        <ul class="title-area">
          <!-- Title Area -->
          <li class="name"></li>
          <li class="toggle-topbar menu-icon"><a href="#"><span>メニュー</span></a></li>
        </ul>
        <section class="top-bar-section">
          <ul class="left">
            <li class="{{(strcmp(URL::full(), URL::to('/')) == 0) ? 'active' : ''}}"><a href="{{URL::to('/')}}">ホーム</a></li>
          </ul>
          <ul class="right">
            @if(Auth::check())

              <!-- if文の解説:現在ページのliクラスにactiveを付加する -->
              <li class="{{ (strpos(URL::current(), URL::to('admin/dash-board'))!== false) ? 'active' : '' }}">
                {{HTML::link('admin/dash-board','ダッシュボード')}}
              </li>
              <li class="{{ (strpos(URL::current(), URL::to('logout'))!== false) ? 'active' : '' }}" >
                {{HTML::link('logout','ログアウト')}}
              </li>
            @else
              <li class="{{ (strpos(URL::current(), URL::to('login'))!== false) ? 'active' : '' }}">
                {{HTML::link('login','ログイン')}}
              </li>
            @endif
          </ul>
        </section>
      </nav>
      <div class="sub-header">
        <hgroup>
          <h1>{{HTML::link('/','Laravelブログ')}}</h1>
          <h2>Laravelでブログ作成</h2>
        </hgroup>
      </div>
    </header>
  </div>
  <div class="row">
    {{$main}}
  </div>
  <div class="row">
    <div class="small-12 large-12 column">
      <footer class="site-footer"></footer>
    </div>
  </div>
</div>
{{ HTML::script('./assets/js/vendor/jquery.js') }}
{{ HTML::script('./assets/js/foundation.min.js') }}
<script>
  $(document).foundation();
</script>
</body>
</html>

※注意:マスターレイアウトをすべてのコントローラーで継承する方法
BaseControllerに以下の記述を追加することで実現可能です。


protected $layout='master';

プログラミングの前半部分でfoundation.cssを読み込んでいることがわかるかと思います。
CSS部分を多少カスタマイズしたファイルはgithubで配布しています。
以下のリンクからDLしてご利用ください<(_ _)>
Laravel ブログ foundation

つづいて、その他のビューを作成していきます。
尚、ビューファイルの全体構造としては、以下のとおりになります。

■ commentsフォルダ
 ∟ commentform.blade.php
 ∟ list.blade.php
 ∟ show.blade.php

■ postsフォルダ
 ∟ edit.blade.php
 ∟ list.blade.php
 ∟ new.blade.php
 ∟ single.blade.php

■ usrsフォルダ
 ∟ login.blade.php
 ∟ newaccount.blade.php

■ dash.blade.php
■ home.blade.php
■ index.blade.php
■ master.blade.php
■ sidebar.blade.php

これから上記のファイルの全コードを書いていくわけですが、とても簡単なので解説は省きます。一点だけ、注意点があります。
コードの場所:app/views/dash.blade.php


<div class="small-9 large-9 column">
  <div class="content">
    <!-- foundationのReveal Modal pluginがajaxをサポートしています -->
    <!-- 最後のdiv要素はAjaxでコンテンツを出力しますが、これはfoundationのReveal Modal pluginが利用されています -->
    @if(Session::has('success'))
    <div data-alert class="alert-box round">
      {{Session::get('success')}}
      <a href="#" class="close">&times;</a>
    </div>
    @endif
    {{$content}}
  </div>
  <div id="comment-show" class="reveal-modal small" data-reveal>
    {{-- Ajaxを利用 --}}
  </div>
</div>

ここの部分だけ少し特殊になっています。
foundationにはreveal-modalというプラグインが入っており、上記のコードを書くだけで、コメントをAjaxで表示/非表示ができるようです。
もっと詳しく知りたいって人は以下のリンクからどうぞ。
Reveal Modal | Foundation Docs

残りのビューファイルは以下からDLしてご利用ください。
manabubannai/laravel_cms

以上です。参考になれば幸いです( ◜◡‾)

photo credit: moominsean via photopin cc

※P.S:無料メルマガで発信中:過去の僕は「ブログ発信で5億円」を稼ぎました。次は「30億円」を目指します。挑戦しつつ、裏側の思考を「メルマガ」から発信します。不満足なら1秒で解約できます。無料登録は「こちら」です。