0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Laravel を使って簡単なCRUD機能を実装 ③

Posted at

キーワード検索機能の追加

スクリーンショット 2025-03-19 074740.png

今回はこのように検索機能をつけて投稿の中から検索キーワードの文字列に合致する記事を表示してくれるようにした。

1. Controllerへの追加点

以下の関数を追加する

 public function search(Request $request)
 {
    $query = $request->input('query');

    $posts = Post::where('title', 'like', "%{$query}%")
                 ->orWhere('body', 'like', "%{$query}%")
                 ->latest()
                 ->get();

    return view('post.search', compact('posts'));
 }

以下説明

public function search(Request $request)

public function search
→ search という名前の関数(メソッド)を作っています。これはコントローラー内で定義され、外部からアクセスできる関数です。

(Request $request)
→ ユーザーが送信したデータ(検索キーワードなど)を受け取るための Request オブジェクトを引数として受け取っています。

$query = $request->input('query');

$request->input('query')
→ ユーザーが検索フォームで入力した値を取得しています。
→ 例えば、ユーザーが「Laravel」と入力した場合、$query には "Laravel" という文字列が入ります。

$posts = Post::where('title', 'like', "%{$query}%")
             ->orWhere('body', 'like', "%{$query}%")
             ->latest()
             ->get();

ここでデータベースの posts テーブルから検索を行っています。

Post::where('title', 'like', "%{$query}%")
Post は、posts テーブルを操作するための Eloquent モデル です。
Eloquentモデルとは、LaravelのORM(Object-Relational Mapping)であるEloquentが提供する、データベースとPHPのオブジェクトを簡単に操作できる機能のことです。Eloquentモデルを使うことで、SQLを書かずにデータベースのレコードを操作できます。

where('title', 'like', "%{$query}%")
は、title カラム(列)に $query の文字列を含むデータを検索します。

LIKE は SQL の検索条件で、"%{$query}%" は、query という単語を含む(前後にどんな文字があってもOK)データを探すための書き方です。例えば、$query = "Laravel" の場合、以下のような title を持つ投稿がヒットします:

"Laravel 入門"
"Laravel の基本"
"初めての Laravel"
orWhere('body', 'like', "%{$query}%")
orWhere は "または(OR)" の条件を追加します。
body カラム(記事の本文)にも $query が含まれるデータも検索対象にします。
->latest()
latest() は、新しい投稿から順番に並べるためのものです。

->get()
get() を使うことで、検索結果をすべて取得します。

return view('post.search', compact('posts'));

view('post.search', compact('posts'))
→ post.search というビュー(画面)に posts のデータを渡して表示します。

compact('posts')
→ これは ['posts' => $posts] と同じ意味で、ビューに posts という変数名で検索結果を渡しています。

2. ビューの作成 

index.blade.php に以下のコードを追加

    <!-- 検索フォームをスタイリング -->
    <div class="max-w-7xl mx-auto px-6 mt-4">
        <form action="{{ route('post.search') }}" method="GET" class="flex gap-2 mb-6">
            <input type="text" name="query" placeholder="検索キーワードを入力"
                   class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
            <button type="submit" class="px-4 py-2 bg-blue-500 text-white font-semibold rounded-lg hover:bg-blue-600">
                検索
            </button>
        </form>
    </div>

以下説明

<form action="{{ route('post.search') }}" method="GET" class="flex gap-2 mb-6">

action="{{ route('post.search') }}"
→ post.search ルートに検索キーワードを GET 送信

method="GET"
→ URLのクエリパラメータとして検索ワードを送る(例: /search?query=Laravel)

また新しくsearch.blade.php を作成し以下のようにビューを作成

<!-- resources/views/post/search.blade.php -->
<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
            🔍 検索結果
        </h2>
    </x-slot>

    <div class="max-w-7xl mx-auto px-6">
        <!-- 検索フォーム -->
        <form action="{{ route('post.search') }}" method="GET" class="flex gap-2 my-6">
            <input type="text" name="query" placeholder="検索キーワードを入力" 
                   value="{{ request('query') }}"
                   class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
            <button type="submit" class="px-4 py-2 bg-blue-500 text-white font-semibold rounded-lg hover:bg-blue-600">
                検索
            </button>
        </form>

        <!-- 検索結果 -->
        @if ($posts->isEmpty())
            <p class="text-gray-500 text-center py-6">該当する投稿がありません</p>
        @else
            @foreach($posts as $post)
            <div class="mt-4 p-8 bg-white w-full rounded-2xl">
                <h1 class="p-4 text-lg font-semibold">
                    件名
                    <a href="{{route('post.show',$post)}}" class="text-blue-600">
                        {{$post->title}}
                    </a>
                </h1>
                <hr class="w-full">
                <p class="mt-4 p-4">
                    {{$post->body}}
                </p>
                @if($post->image)
                    <img src="{{ asset('storage/' . $post->image) }}" alt="投稿画像" style="max-width:200px;">
                @endif
                <div class="p-4 text-sm font-semibold">
                    <p>
                        {{$post->created_at}} / {{ optional($post->user)->name ?? 'ゲスト' }}
                    </p>
                </div>
            </div>
            @endforeach
        @endif
    </div>
</x-app-layout>

以下説明

<form action="{{ route('post.search') }}" method="GET" class="flex gap-2 my-6">
    <input type="text" name="query" placeholder="検索キーワードを入力" 
           value="{{ request('query') }}"
           class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
    <button type="submit" class="px-4 py-2 bg-blue-500 text-white font-semibold rounded-lg hover:bg-blue-600">
        検索
    </button>
</form>

この form のコードは、検索キーワードを入力し、ボタンを押すことで、特定のページに遷移し、検索結果を表示する という動作を実現しています。

action="{{ route('post.search') }}"
→ 検索の GET リクエストを送信

value="{{ request('query') }}"
これにより、検索ワードを保持(再検索時に入力欄に前回の検索ワードを残す)

@if ($posts->isEmpty())
    <p class="text-gray-500 text-center py-6">該当する投稿がありません</p>
@else

$posts->isEmpty() → 結果がない場合、メッセージを表示

@foreach($posts as $post)
    <div class="mt-4 p-8 bg-white w-full rounded-2xl">

foreach($posts as $post) → posts のデータを1件ずつ表示

@if($post->image)
    <img src="{{ asset('storage/' . $post->image) }}" alt="投稿画像" style="max-width:200px;">
@endif

if($post->image) → 画像がある場合のみ表示

asset('storage/' . $post->image)
→ storage フォルダ内の画像を表示

<div class="p-4 text-sm font-semibold">
    <p>
        {{$post->created_at}} / {{ optional($post->user)->name ?? 'ゲスト' }}
    </p>
</div>

$post->created_at → 投稿日時を表示
optional($post->user)->name ?? 'ゲスト'

投稿者名を表示(ユーザー情報が null の場合 "ゲスト" にする)

スクリーンショット 2025-03-19 095207.png

このようなフォームを作成することができる。

form> の action とは?

form> タグの action 属性は、フォームの送信先(リクエストを送るURL) を指定します。

<form action="送信先のURL" method="GET">

例えば、以下のように書くと、https://example.com/search にリクエストが送られます。

<form action="/search" method="GET">

method="GET" は、HTML の

タグで使用される属性で、フォームデータを送信する際の HTTP メソッドを指定するものです。このフォームでは、「検索キーワードを入力」→「検索ボタンを押す」 と、GET リクエストが /search に送信されます。
GET は主に 検索やページ遷移など、データを取得する目的 で使われます。GET リクエストでは、フォームの入力データが URL にクエリパラメータとして付加されます。
https://example.com/search?query=Laravel

route('post.search') の意味

Laravelでは、ルート(ページのURL)を route('ルート名') という形で取得できます。
これは、routes/web.php に定義されたルート名に対応するURLを動的に取得するためのものです。ルートに例えば

Route::get('/search', [PostController::class, 'search'])->name('post.search');

ここで name('post.search') を付けたことで、
route('post.search') は /search というURLを表す ようになります。

0
0
0

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?