読者です 読者をやめる 読者になる 読者になる

@半径とことこ60分

人間の認知範囲なんてそんなもんさと、鳥が囀った

プログラマーじゃないけどLaravel4入門(6)blogをつくる

バックエンド/記事新規作成、編集、削除(続きの続き)

よく分からないエラーが出た時は dump-autoload を試してみよう

どんなエラーだったかはトレースし忘れたのですが、前回の一覧表示のチェック時には結構手間取りました。結局、コントローラーをサブディレクトリ backend に移動させたためにクラスが見つからなかったということのようです。

Laravel4のオートロード
Laravel4、アップデートとトラブルシューティング

完全に理解できたとは言い難いのですが、上記サイトを参考に何とか一覧表示成功となりました。

f:id:ausnichts:20140808163821p:plain

新規作成、編集 controllers/backend/ArticlesController.php

public function create()
{
  return View::make('backend.articles.create');

public function store()
{
  $validator = Validator::make($data = Input::all(), Article::$rules);
  if ($validator->fails())
  {
    return Redirect::back()->withErrors($validator)->withInput();
  }
  $data['is_published'] = isset($data['is_published']) ? true : false;
  Article::create($data);
  Notification::success('Article was successfully added');
  return Redirect::action('ArticlesController@index');
}

public function edit($id)
{
  try
  {
    $article = Article::findOrFail($id);
    return View::make('backend.articles.edit', compact('article'));
  }
  catch(ModelNotFoundException $e)
  {
    Notification::error('Not Found');
    return Redirect::action('ArticlesController@index');
  }
}

public function update($id)
{
  try
  {
    $article = Article::findOrFail($id);
  }
  catch(ModelNotFoundException $e)
  {
    Notification::error('Not Found');
    return Redirect::action('ArticlesController@index');
  }
  $validator = Validator::make($data = Input::all(), Article::$rules);
  if ($validator->fails())
  {
    return Redirect::back()->withErrors($validator)->withInput();
  }
  $data['is_published'] = isset($data['is_published']) ? true : false;
  $article->update($data);
  Notification::success('Article was successfully updated');
  return Redirect::action('ArticlesController@index');
}

バリデーションは、models/Article.php に書いています。

class Article extends \Eloquent {
  // Add your validation rules here
  public static $rules = [
    'title' => 'required',
    'content' => 'required',
    //'category_id' => 'exists:categories,id'
  ];
  // Don't forget to fill this array
  protected $guarded = ['id'];
}

edvinaskrucas/notification 導入

エラーや完了通知の表示用に notification パッケージを導入してみました。

edvinaskrucas/notification · GitHub

インストール方法は readme に詳しく書かれています。で、削除にも追加です。

public function destroy($id)
{
  Article::destroy($id);
  Notification::success('Article was successfully deleted');
  return Redirect::action('ArticlesController@index');

}

一覧ビューに通知表示の制御文と消去スクリプトを追加です。
app/views/backend/articles/index.blade.php

@section('content')
  <h1 class="page-header">記事一覧</h1>
  {{ Notification::showAll() }}
  <div class="pull-left">

(略)

(最終行)

@section('script')
@parent
  <script type="text/javascript">
    $(document).ready(function () {
      setTimeout(function(){
        $('.alert').slideUp();
        },3000);
    });
  </script>
@stop

新規作成ビュー app/views/backend/articles/create.blade.php

@extends('backend.master')
@section('title')
  記事作成 - @parent
@stop

@section('content')
  <h1 class="page-header">記事作成</h1>
  {{ Form::open(array('action' => 'ArticlesController@store', 'class' => 'form-horizontal', 'role' => 'form')) }}

  <!-- Title -->
  <div class="form-group has-feedback {{ $errors->has('title') ? 'has-error' : '' }}">
    <label class="control-label col-sm-2" for="title">タイトル</label>
    <div class="col-sm-10">
      {{ Form::text('title', null, array('class'=>'form-control', 'id' => 'title', 'placeholder'=>'タイトル')) }}
@if ($errors->first('title'))
      <span class="help-block">{{ $errors->first('title') }}</span>
@endif
    </div>
  </div>

  <!-- Published -->
  <div class="form-group">
    <label class="control-label col-sm-2" for="is_published">公開</label>
    <div class="col-sm-10">
      {{ Form::checkbox('is_published', 'is_published', null, array('id' => 'is_published')) }}
    </div>
  </div>

  <!-- Category -->
  <div class="form-group has-feedback {{ $errors->has('category_id') ? 'has-error' : '' }}">
    <label class="control-label col-sm-2" for="category_id">カテゴリ</label>
    <div class="col-sm-10">
      <!--カテゴリリスト-->
    </div>
  </div>

  <!-- Content -->
  <div class="form-group has-feedback {{ $errors->has('content') ? 'has-error' : '' }}">
    <label class="control-label col-sm-2" for="content">記事内容</label>
    <div class="col-sm-10">
      {{ Form::textarea('content', null, array('class'=>'ckeditor form-control', 'id' => 'content', 'placeholder'=>'記事内容')) }}
@if ($errors->first('content'))
      <span class="help-block">{{ $errors->first('content') }}</span>
@endif
    </div>
  </div>

  <!-- Form actions -->
  {{ Form::submit('Save Changes', array('class' => 'btn btn-success')) }}
    <a href="{{ url('backend/articles') }}" class="btn btn-default">&nbsp;Cancel</a>
  {{ Form::close() }}
@stop

@section('script')
@parent
  {{ HTML::script('ckeditor/ckeditor.js') }}
@stop

編集ビュー app/views/backend/articles/edit.blade.php

@extends('backend.master')
@section('title')
  記事編集 - @parent
@stop

@section('content')
  <h1 class="page-header">記事編集</h1>
  {{ Form::open(array('action' => array('ArticlesController@update', $article->id), 'class' => 'form-horizontal', 'role' => 'form', 'method' => 'PUT')) }}

  <!-- Title -->
  <div class="form-group has-feedback {{ $errors->has('title') ? 'has-error' : '' }}">
    <label class="control-label col-sm-2" for="title">タイトル</label>
    <div class="col-sm-10">
      {{ Form::text('title', $article->title, array('class'=>'form-control', 'id' => 'title', 'placeholder'=>'タイトル')) }}
@if ($errors->first('title'))
      <span class="help-block">{{ $errors->first('title') }}</span>
@endif
    </div>
  </div>

  <!-- Published -->
  <div class="form-group">
    <label class="control-label col-sm-2" for="is_published">公開</label>
    <div class="col-sm-10">
      {{ Form::checkbox('is_published', 'is_published',$article->is_published, array('id' => 'is_published')) }}
    </div>
  </div>

  <!-- Category -->
  <div class="form-group has-feedback {{ $errors->has('category_id') ? 'has-error' : '' }}">
    <label class="control-label col-sm-2" for="category_id">カテゴリ</label>
    <div class="col-sm-10">
      <!--カテゴリリスト-->
    </div>
  </div>

  <!-- Content -->
  <div class="form-group has-feedback {{ $errors->has('content') ? 'has-error' : '' }}">
    <label class="control-label col-sm-2" for="content">記事内容</label>
    <div class="col-sm-10">
      {{ Form::textarea('content', $article->content, array('class'=>'ckeditor form-control', 'id' => 'content', 'placeholder'=>'記事内容')) }}
@if ($errors->first('content'))
      <span class="help-block">{{ $errors->first('content') }}</span>
@endif
    </div>
  </div>

  <!-- Form actions -->
  {{ Form::submit('Save Changes', array('class' => 'btn btn-success')) }}
    <a href="{{ url('backend/articles') }}" class="btn btn-default">&nbsp;Cancel</a>
  {{ Form::close() }}
@stop

@section('script')
@parent
  {{ HTML::script('ckeditor/ckeditor.js') }}
@stop

新規作成や編集時にバリデーションエラーが出た場合、入力画面に戻った時の入力データの保持はどうするんだろうと疑問でしたが、

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

としておけば、withInput() がそれぞれデータを処理してくれるんですね。 

WYGIWYGエディター CKEditor

記事入力にWYGIWYGエディターがあった方がいいですね。CKEditor が簡単そうですので Standard editor を入れてみます。

CKEditor.com | The best web text editor for everyone

Standard Package をダウンロード、解凍し、public 以下に sample,adapters ディレクトリや readme など不要ファイルをのぞいて丸ごと入れます。 後は、textarea に class="ckeditor" を追加するだけで使用可能になります。

ということで、記事の一覧、新規入力、編集、削除が完成しました。

f:id:ausnichts:20140817153606p:plain

次は、カテゴリ関連のスクリプトと記事データとのリレーションです。