はじめての方へ・ステップ 10 / 12
フォームから保存する
新しいメモを書くフォームを作り、送られた内容をチェックしてから保存します。@csrf・バリデーション・入力の引き継ぎ(old)・保存のあとのお知らせ(フラッシュメッセージ)を説明します。
いよいよ、画面から新しいメモを書いて保存できるようにします。フォームから届く入力は、空っぽだったり、長すぎたりすることがあります。保存する前に、入力が正しいかをバリデーション(入力のチェック)で確かめます。このページでは、create(作成のフォーム)と store(保存)の2つのメソッドを作ります。
フォームのページを作る(create)#
MemoController の create メソッドに、フォームのビューを返す処理を書きます。
public function create()
{
return view('memos.create');
}
resources/views/memos/create.blade.php を作ります。
<x-layout>
<x-slot:title>新しいメモ</x-slot>
<h1>新しいメモ</h1>
<form method="POST" action="{{ route('memos.store') }}">
@csrf
<p>
<label for="title">タイトル</label><br>
<input type="text" id="title" name="title" value="{{ old('title') }}">
</p>
@error('title')
<p>{{ $message }}</p>
@enderror
<p>
<label for="body">本文</label><br>
<textarea id="body" name="body" rows="5">{{ old('body') }}</textarea>
</p>
@error('body')
<p>{{ $message }}</p>
@enderror
<button type="submit">保存する</button>
</form>
<p><a href="{{ route('memos.index') }}">一覧へ戻る</a></p>
</x-layout>
ポイントを見ていきます。
method="POST"とaction="{{ route('memos.store') }}":送り先はPOST /memos、つまりstoreメソッドです@csrf:ほかのサイトがなりすまして送ってくる攻撃を防ぐ「合言葉」を、隠れた入力欄として入れます。POSTのフォームには必ず書きます。書き忘れると、送ったときに「419 Page Expired」というエラーになります。くわしくは CSRF 対策name="title"とname="body":コントローラーは、この名前で入力を受け取ります。表の列の名前とそろえておくと分かりやすくなりますold('title'):チェックに引っかかって戻ってきたとき、さっき打った内容を入れ直します。打ち直さなくてすみます@error('title')…@enderror:titleがチェックに引っかかったときだけ、中身を出します。中の$messageには、何がだめだったかの文が入ります
一覧のページから、このフォームへ行けるようにしておきましょう。resources/views/memos/index.blade.php の <h1> の下に、次の1行を足します。
<p><a href="{{ route('memos.create') }}">新しいメモを書く</a></p>
チェックして保存する(store)#
store メソッドを次のように書きます。
public function store(Request $request)
{
// 送られてきた入力をチェックする。だめなら、ここで止まって入力の画面へ戻る
$validated = $request->validate([
'title' => ['required', 'max:100'],
'body' => ['nullable', 'max:2000'],
]);
// チェックを通った値だけで、メモを作って保存する
Memo::create($validated);
return redirect()->route('memos.index')->with('status', 'メモを保存しました。');
}
$request->validate()#
$request には、ブラウザから届いたリクエストの中身が入っています。validate() に「どの入力に、どんなルールを当てるか」を渡すと、チェックしてくれます。
| ルール | 意味 |
|---|---|
required |
入っていなければだめ(空っぽはだめ) |
max:100 |
100 文字まで |
nullable |
空っぽでもよい |
- 全部通ったとき:チェックを通った入力だけが配列で返り、
$validatedに入ります。そのまま下の行へ進みます - 1つでも通らなかったとき:そこで止まり、Laravel が自動で前の画面(フォーム)へ戻します。そのとき、エラーの文と、さっきの入力もいっしょに持って帰るので、フォームの
@errorとold()が働きます
ルールは、ほかにもたくさんあります。全部の一覧はバリデーションのルール一覧にまとめています。
Memo::create($validated)#
前のページで、モデルに #[Fillable(['title', 'body'])] を書いたので、チェックを通った配列をそのまま渡して保存できます。
redirect()->route()->with()#
保存したら、一覧のページへ移動させます(リダイレクト)。with('status', 'メモを保存しました。') は、「次の1回だけ、status という名前でこの文を覚えておく」という意味です。このように、次のページで1回だけ使う値をフラッシュデータと呼びます。
保存のお知らせを出す#
覚えておいた文を、どのページでも出せるように、共通の枠 resources/views/components/layout.blade.php の <main> の中を書きかえます。
<main>
@if (session('status'))
<p><strong>{{ session('status') }}</strong></p>
@endif
{{ $slot }}
</main>
session('status') で、さっき覚えた文を取り出しています。入っているときだけ、太字で表示されます。
試してみる#
- 一覧の「新しいメモを書く」を押す
- タイトルを空っぽのまま「保存する」を押す → フォームに戻り、タイトルの下に
The title field is required.と出る。本文に書いた内容は残っている - タイトルを書いて「保存する」を押す → 一覧に戻り、「メモを保存しました。」と出て、新しいメモが並んでいる
補足
エラーの文は、はじめは英語です。日本語にするには、言語のファイルを用意します。やり方はバリデーション(入力のチェック)と多言語対応(ローカライズ)にまとめています。
注意
フォームを送って「419 Page Expired」と出たら、<form> の中に @csrf を書き忘れていないかを見てください。
次に読むページ#
公式ドキュメント(英語)
2026年10月5日時点の内容をもとに、日本語でまとめています。