本文へ移動
Laravel Tips

はじめての方へ・ステップ 10 / 12

フォームから保存する

新しいメモを書くフォームを作り、送られた内容をチェックしてから保存します。@csrf・バリデーション・入力の引き継ぎ(old)・保存のあとのお知らせ(フラッシュメッセージ)を説明します。

いよいよ、画面から新しいメモを書いて保存できるようにします。フォームから届く入力は、空っぽだったり、長すぎたりすることがあります。保存する前に、入力が正しいかをバリデーション(入力のチェック)で確かめます。このページでは、create(作成のフォーム)と store(保存)の2つのメソッドを作ります。

フォームのページを作る(create)#

MemoController の create メソッドに、フォームのビューを返す処理を書きます。

php
public function create()
{
    return view('memos.create');
}

resources/views/memos/create.blade.php を作ります。

blade
<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行を足します。

blade
<p><a href="{{ route('memos.create') }}">新しいメモを書く</a></p>

チェックして保存する(store)#

store メソッドを次のように書きます。

php
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> の中を書きかえます。

blade
<main>
    @if (session('status'))
        <p><strong>{{ session('status') }}</strong></p>
    @endif

    {{ $slot }}
</main>

session('status') で、さっき覚えた文を取り出しています。入っているときだけ、太字で表示されます。

試してみる#

  1. 一覧の「新しいメモを書く」を押す
  2. タイトルを空っぽのまま「保存する」を押す → フォームに戻り、タイトルの下に The title field is required. と出る。本文に書いた内容は残っている
  3. タイトルを書いて「保存する」を押す → 一覧に戻り、「メモを保存しました。」と出て、新しいメモが並んでいる

補足

エラーの文は、はじめは英語です。日本語にするには、言語のファイルを用意します。やり方はバリデーション(入力のチェック)と多言語対応(ローカライズ)にまとめています。

注意

フォームを送って「419 Page Expired」と出たら、<form> の中に @csrf を書き忘れていないかを見てください。

次に読むページ#

公式ドキュメント(英語)

2026年10月5日時点の内容をもとに、日本語でまとめています。

ページの一覧