前回は、既存記事の編集処理を実装しました。今回はブログ記事を削除する処理を実装していきます。
ルーティングの追加
routes/web.php
を開き、下記1行追加して、削除用のルーティングを追加します。
Route::post('admin/delete', 'AdminBlogController@delete')->name('admin_delete');
モデルの編集
ソフトデリート(論理削除)をしたいので、その設定をします。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
を開いて、元々のフォームに下に、新たなフォームを作成して、そこに削除ボタンを追加します。
{{-- 元々のフォーム --}}
<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
を開いて下記のように編集します。
<?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 メソッドを追加します。
/**
* ブログ記事削除処理
*
* @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
カラムに削除日が入り、論理削除になるかどうかを確認してください。
今回は短いですが以上です。次回は、記事一覧画面を実装していきます。