Создание простого блога на Laravel 11: Добавление пагинации и поиска

Создание простого блога на Laravel 11: Добавление пагинации и поиска

В прошлой статье мы реализовали CRUD функционал для постов. В этой статье мы добавим пагинацию и поиск постов для нашего блога.

Реализация пагинации на Laravel

Laravel поддерживает пагинацию «из коробки». В предыдущей статье мы уже использовали метод paginate(). Теперь добавим оформление для удобства работы с постами.

Про пагинацию более подробно вы можете почитать в официальной документации Laravel.

Добавляем пагинацию в контроллер

Обновим метод index в PostController:

public function index(Request $request)
{
    $search = $request->query('search'); // Получаем запрос поиска из URL

    $posts = Post::query()
        ->when($search, function ($query, $search) {
            $query->where('title', 'like', "%{$search}%"); // Фильтрация по заголовку
        })
        ->latest()
        ->paginate(5); // Пагинация: 5 записей на страницу

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

Здесь:

  • Мы добавили параметр $search для фильтрации постов.
  • Использовали метод when() для условного применения поиска.
  • Установили пагинацию на 5 записей на страницу.

Обновление шаблона для пагинации

В шаблоне resources/views/posts/index.blade.php добавим ссылки пагинации.

Список постов с пагинацией

Заменим вызов пагинации, отобразив стиль Bootstrap для пагинации:

{{ $posts->links('pagination::bootstrap-5') }}

Добавляем форму поиска

Перед таблицей с постами добавим форму поиска:

<form action="{{ route('posts.index') }}" method="GET" class="mb-4">
    <div class="input-group">
        <input type="text" name="search" class="form-control" placeholder="Искать посты..." value="{{ $search }}">
        <button class="btn btn-outline-secondary" type="submit">Найти</button>
    </div>
</form>

Теперь, когда пользователь вводит запрос и нажимает «Найти», URL будет выглядеть как /search?search=example.

Улучшение UX при отсутствии постов

Если постов нет, мы добавим сообщение в шаблоне posts/index.blade.php:

@if($posts->isEmpty())
    <p>Посты не найдены.</p>
@else
    <table class="table">
        <thead>
            <tr>
                <th>ID</th>
                <th>Заголовок</th>
                <th>Автор</th>
                <th>Действия</th>
            </tr>
        </thead>
        <tbody>
            @foreach($posts as $post)
                <tr>
                    <td>{{ $post->id }}</td>
                    <td>{{ $post->title }}</td>
                    <td>{{ $post->author }}</td>
                    <td>
                        <a href="{{ route('posts.edit', $post) }}" class="btn btn-warning">Редактировать</a>
                        <form action="{{ route('posts.destroy', $post) }}" method="POST" style="display:inline-block">
                            @csrf
                            @method('DELETE')
                            <button class="btn btn-danger" onclick="return confirm('Удалить пост?')">Удалить</button>
                        </form>
                    </td>
                </tr>
            @endforeach
        </tbody>
    </table>
    {{ $posts->links('pagination::bootstrap-5') }}
@endif

Теперь, если поиск не дал результатов, будет выводиться сообщение «Посты не найдены».

Итог изменений

После всех изменений:

  • На главной странице будет форма поиска.
  • Отображается только 5 постов на одной странице.
  • Пагинация позволяет перемещаться между страницами.

Итоговый код

Метод index в контроллере PostController:

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

    $posts = Post::query()
        ->when($search, function ($query, $search) {
            $query->where('title', 'like', "%{$search}%");
        })
        ->latest()
        ->paginate(5);

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

Шаблон posts/index.blade.php:

@extends('layout')

@section('content')
    <h1>Список постов</h1>
    <a href="{{ route('posts.create') }}" class="btn btn-primary mb-3">Создать пост</a>

    <form action="{{ route('posts.index') }}" method="GET" class="mb-4">
        <div class="input-group">
            <input type="text" name="search" class="form-control" placeholder="Искать посты..." value="{{ $search }}">
            <button class="btn btn-outline-secondary" type="submit">Найти</button>
        </div>
    </form>

    @if($posts->isEmpty())
        <p>Посты не найдены.</p>
    @else
        <table class="table">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Заголовок</th>
                    <th>Автор</th>
                    <th>Действия</th>
                </tr>
            </thead>
            <tbody>
                @foreach($posts as $post)
                    <tr>
                        <td>{{ $post->id }}</td>
                        <td>{{ $post->title }}</td>
                        <td>{{ $post->author }}</td>
                        <td>
                            <a href="{{ route('posts.edit', $post) }}" class="btn btn-warning">Редактировать</a>
                            <form action="{{ route('posts.destroy', $post) }}" method="POST" style="display:inline-block">
                                @csrf
                                @method('DELETE')
                                <button class="btn btn-danger" onclick="return confirm('Удалить пост?')">Удалить</button>
                            </form>
                        </td>
                    </tr>
                @endforeach
            </tbody>
        </table>
        {{ $posts->links('pagination::bootstrap-5') }}
    @endif
@endsection

Следующие шаги по блогу на Laravel

В следующий статье мы добавим авторизацию пользователей в блог и ограничим доступ, чтобы пользователи могли изменять и удалять только свои посты.

LiveTnternet Rating and Statistic
Подписаться
Уведомить о
guest
1 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Данир
Данир
1 месяц назад

Супер

1
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x