🙆

【Laravel】未入力の場合は値を保持したまま遷移させる

2024/04/15に公開

はじめに

投稿を編集する画面で未入力の場合は元の値を保持して一覧画面(index)に遷移させようとしたときに詰まったので、備忘録がてらどう解決したかを共有します!

以下のような基本的な編集画面です

試したこと

public function update(Request $request, $id)
{
    $post = Post::findOrFail($id);

    $validatedData = $request->validate([
        'title' => 'nullable|max:255',
        'about' => 'nullable|max:255',
        'content' => 'nullable',
        'tags' => 'nullable|string',
    ]);

    if ($request->filled('title') || $request->filled('about') || $request->filled('content')) {
        $post->update($validatedData);
    }

    // タグの更新処理
    $post->tags()->detach();
    if ($request->filled('tags')) {
        $tags = explode(',', $request->input('tags'));
        $tags = array_map('trim', $tags);
        $tags = array_filter($tags);

        foreach ($tags as $tagName) {
            $tag = Tag::firstOrCreate(['name' => $tagName]);
            $post->tags()->attach($tag);
        }
    }

    return redirect()->route('conduit.index')->with('success', '投稿が更新されました');
}

・バリデーションルールをrequiredからnullableに変更

・入力がない場合でもバリデーションをパスする

・if文でタイトル、概要、本文のいずれかに入力がある場合にのみ更新

しかしこれでは二つの問題点がありました
・元の値が保存されていない
・NOT NULLのカラムでエラーが出る

そこでif文でリクエストに値が入っていればtrueを、入っていなければfalseでそれぞれの値に二つの条件分岐を書いたらいいんではないかと考えました。

解決策

public function update(Request $request, $id)
{
    $post = Post::findOrFail($id);
    $validatedData = $request->validate([
        'title' => 'nullable|max:255',
        'about' => 'nullable|max:255',
        'content' => 'nullable',
        'tags' => 'nullable|array',
    ]);

    $post->title = $request->filled('title') ? $request->input('title') : $post->title;
    $post->about = $request->filled('about') ? $request->input('about') : $post->about;
    $post->content = $request->filled('content') ? $request->input('content') : $post->content;
    $post->save();

    // タグの更新処理(storeと同じ)
    $post->tags()->detach();
    if ($request->filled('tags')) {
        $tags = explode(',', $request->input('tags'));
        $tags = array_map('trim', $tags);
        $tags = array_filter($tags);
        foreach ($tags as $tagName) {
            $tag = Tag::firstOrCreate(['name' => $tagName]);
            $post->tags()->attach($tag);
        }
    }

    return redirect()->route('conduit.index')->with('success', '投稿が更新されました');
}

結論として、三項演算子で書くとうまくいきました!

ちなみに三項演算子は、条件式 ? 式1 : 式2の形式で書く条件分岐式です。

条件式がtrueの場合は、式1が評価され、その結果が返される
条件式がfalseの場合は、式2が評価され、その結果が返される、てな感じです。

$post->title = $request->filled('title') ? $request->input('title') : $post->title;

この処理は、リクエスト(送信された値)にtitleが入力されていたらtrueになり、入力された値がtitleに代入されます。

逆にリクエストにtitleが入っていなければfalseになり元々の値がtitleに代入されます。

aboutとcontentも同様に記述することで全て、または一部が未入力の場合でも値を適切に保持&更新ができるようになりました!

ではまた!

Discussion