LoginSignup
4
2

More than 5 years have passed since last update.

Laravel5 チュートリアル ブログもどきを作る(5) ブログ記事を削除する

Last updated at Posted at 2018-07-08

前回は、既存記事の編集処理を実装しました。今回はブログ記事を削除する処理を実装していきます。

ルーティングの追加

routes/web.php を開き、下記1行追加して、削除用のルーティングを追加します。

routes/web.php
Route::post('admin/delete', 'AdminBlogController@delete')->name('admin_delete');

モデルの編集

ソフトデリート(論理削除)をしたいので、その設定をします。app/Models/Article.php を開いて、下記のように編集します。

app/Models/Article.php
<?php

namespace App\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Article extends Model
{
    // SoftDeletes トレイトを使う
    use SoftDeletes;

    ...中略...

    // $dates プロパティには、日時が入るカラムを設定する(日付ミューテタ)
    // そうすると、その値が自動的に Carbon インスタンスに変換される
    protected $dates = ['post_date', 'created_at', 'updated_at', 'deleted_at'];

    ...中略...
}

このように use SoftDeletes; と書き、$dates プロパティに deleted_at カラムを指定するだけで、削除実行時 deleted_at カラムに、削除日時が入り、論理削除となります。詳しくは日本語ドキュメントを参照してください。

View テンプレートの編集

resources/views/admin_blog/form.blade.php を開いて、元々のフォームに下に、新たなフォームを作成して、そこに削除ボタンを追加します。

resources/views/admin_blog/form.blade.php
            {{-- 元々のフォーム --}}
            <form method="POST" action="{{ route('admin_post') }}">
            ... (中略) ...
            </form>

            @if ($article_id)
                <br>
                <form action="{{ route('admin_delete') }}" method="POST">
                    <input type="submit" class="btn btn-primary btn-sm" value="削除">
                    <input type="hidden" name="article_id" value="{{ $article_id }}">
                    {{ csrf_field() }}
                </form>
            @endif

新たにフォームを作成しているため「送信」ボタンと「削除」ボタンが横並びにならず、少し気持ち悪いですが、とりあえず目をつぶってください。

リクエストクラスの編集

削除のときも、パラメータとして article_id を渡すので、そのバリデートを追加します。 app/Http/Requests/AdminBlogRequest.php を開いて下記のように編集します。

app/Http/Requests/AdminBlogRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Route;

class AdminBlogRequest extends FormRequest
{
    ... 中略...

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        // 現在実行しているアクション名を取得
        // アクション名により、どのルールを使うのか場合分けをしておく
        $action = $this->getCurrentAction();

        $rules['post'] = [
            'article_id' => 'integer|nullable',              // 整数・null でもOK
            'post_date'  => 'required|date',                 // 必須・日付
            'title'      => 'required|string|max:255',       // 必須・文字列・最大値(255文字まで)
            'body'       => 'required|string|max:10000',     // 必須・文字列・最大値(10000文字まで)
        ];

        $rules['delete'] = [
            'article_id' => 'required|integer'     // 必須・整数
        ];

        return array_get($rules, $action, []);
    }

    ... 中略...

    /**
     * 現在実行中のアクション名を返す
     *
     * @return mixed
     */
    public function getCurrentAction()
    {
        // 実行中のアクション名を取得
        // App\Http\Controllers\AdminBlogController@post のような返り値が返ってくるので @ で分割
        $route_action = Route::currentRouteAction();
        list(, $action) = explode('@', $route_action);
        return $action;
    }
}

コントローラーの post()delete() の各メソッドでリクエストクラスを共用するので、それぞれどのアクション(メソッド)が実行されたとき、どのルールを使うのかを区別するために、条件分岐する必要があります。
そこで getCurrentAction() という実行中のアクション(メソッド)名を返す関数を新しく作成して、それを利用しています。実行中のアクション(メソッド)名により、rules() の返す値を変えています。messages() は変更ありません。getCurrentAction() は他のところでも汎用的に使えるメソッドなので、ヘルパー関数として定義するのが良いでしょう(今回は割愛します)。
もちろん、こんな面倒なことをしなくても、最初から、アクション(メソッド)毎に、リクエストクラスを分けるという方法もあります。

コントローラーの編集

続いて削除処理を実装します。app/Http/Controllers/AdminBlogController.php を開いて、下記のように delete メソッドを追加します。

app/Http/Controllers/AdminBlogController.php
    /**
     * ブログ記事削除処理
     *
     * @param AdminBlogRequest $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function delete(AdminBlogRequest $request)
    {
        // 記事IDの取得
        $article_id = $request->input('article_id');

        // Article モデルを取得して delete メソッドを実行することで削除できる
        // このとき万が一 $article が null になる場合も想定して実装するのが良い(今回は紹介のみで使わないので割愛)
//        $article = $this->article->find($article_id);
//        $article->delete();

        // 主キーの値があるなら destroy メソッドで削除することができる
        // 引数は配列でも可。返り値は削除したレコード数
        $result = $this->article->destroy($article_id);
        $message = ($result) ? '記事を削除しました' : '記事の削除に失敗しました。';

        // フォーム画面へリダイレクト
        return redirect()->route('admin_form')->with('message', $message);
    }

削除方法を2通り紹介しました。詳しくは日本語ドキュメントを参照してください。
ここまでできたら、実際に削除ボタンを押してみて、対象レコードの deleted_at カラムに削除日が入り、論理削除になるかどうかを確認してください。

今回は短いですが以上です。次回は、記事一覧画面を実装していきます。

参考資料

Laravel 日本語ドキュメント

プログラムソース(github)

4
2
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2