Лаб. работа 4 "Создание индексных страниц и пагинация"
Цель: Научиться выводить данные из БД на страницы приложения, реализовать пагинацию и фильтрацию, использовать связи между моделями.
Задачи:
- Создать страницу со списком постов.
- Реализовать пагинацию и сортировку.
- Отображать связанные данные (категории, теги, комментарии).
- Стилизовать интерфейс с использованием Tailwind CSS.
Методическая часть
1. Создание контроллера и маршрута
Создайте контроллер
PostController, если он не создан ранее:1php artisan make:controller PostController --resourceДобавьте метод
indexвapp/Http/Controllers/PostController.php:1public function index() { 2 $posts = Post::with(['category', 'tags', 'comments']) 3 ->orderBy('created_at', 'desc') 4 ->paginate(10); 5 return view('posts.index', compact('posts')); 6}Зарегистрируйте маршрут в
routes/web.php:1use App\Http\Controllers\PostController; 2Route::get('/posts', [PostController::class, 'index'])->name('posts.index');
2. Создание Blade-шаблона
- Шаблон списка постов (
resources/views/posts/index.blade.php):1@extends('layouts.app') 2 3@section('content') 4 <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> 5 <h1 class="text-3xl font-bold text-gray-900 mb-8">Все посты</h1> 6 7 <!-- Фильтры и сортировка --> 8 <div class="mb-6 flex justify-between items-center"> 9 <div class="flex space-x-4"> 10 <a href="{{ route('posts.index', ['sort' => 'latest']) }}" 11 class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"> 12 Новые 13 </a> 14 <a href="{{ route('posts.index', ['sort' => 'popular']) }}" 15 class="px-4 py-2 bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300"> 16 Популярные 17 </a> 18 </div> 19 </div> 20 21 <!-- Список постов --> 22 <div class="grid gap-6 md:grid-cols-2 lg:grid-cols-3"> 23 @foreach ($posts as $post) 24 <div class="bg-white rounded-lg shadow-md overflow-hidden"> 25 @if ($post->image) 26 <img src="{{ asset('storage/' . $post->image) }}" 27 alt="{{ $post->title }}" 28 class="w-full h-48 object-cover"> 29 @endif 30 <div class="p-6"> 31 <div class="flex items-center mb-2"> 32 <span class="text-sm text-gray-600"> 33 {{ $post->created_at->format('d.m.Y') }} 34 </span> 35 <span class="mx-2">•</span> 36 <span class="text-sm text-blue-600"> 37 {{ $post->category->name }} 38 </span> 39 </div> 40 <h2 class="text-xl font-semibold text-gray-900 mb-2"> 41 {{ $post->title }} 42 </h2> 43 <p class="text-gray-600 mb-4">{{ Str::limit($post->content, 150) }}</p> 44 <div class="flex items-center justify-between"> 45 <div class="flex space-x-2"> 46 @foreach ($post->tags as $tag) 47 <span class="px-2 py-1 bg-gray-100 text-gray-700 rounded-full text-sm"> 48 {{ $tag->name }} 49 </span> 50 @endforeach 51 </div> 52 <a href="{{ route('posts.show', $post) }}" 53 class="text-blue-600 hover:text-blue-800"> 54 Читать → 55 </a> 56 </div> 57 </div> 58 </div> 59 @endforeach 60 </div> 61 62 <!-- Пагинация --> 63 <div class="mt-8"> 64 {{ $posts->links() }} 65 </div> 66 </div> 67@endsection
3. Кастомизация пагинации
- Создайте файл пагинации для Tailwind:
1php artisan vendor:publish --tag=laravel-pagination - Выберите шаблон
resources/views/vendor/pagination/tailwind.blade.php.
4. Добавление сортировки в контроллер
Модифицируйте метод index для поддержки параметров:
1public function index(Request $request) {
2 $sort = $request->query('sort', 'latest');
3
4 $query = Post::with(['category', 'tags', 'comments']);
5
6 switch ($sort) {
7 case 'popular':
8 $query->withCount('comments')->orderBy('comments_count', 'desc');
9 break;
10 default:
11 $query->orderBy('created_at', 'desc');
12 }
13
14 $posts = $query->paginate(10);
15 return view('posts.index', compact('posts', 'sort'));
16}
Индивидуальные задания
1. Фильтрация по категориям
- Добавьте выпадающий список с категориями в шапку страницы.
- Реализуйте фильтрацию постов по выбранной категории через параметр URL.
Пример кода:
1<select onchange="window.location.href = '{{ route('posts.index') }}?category=' + this.value">
2 <option value="">Все категории</option>
3 @foreach ($categories as $category)
4 <option value="{{ $category->id }}" {{ $category->id == request('category') ? 'selected' : '' }}>
5 {{ $category->name }}
6 </option>
7 @endforeach
8</select>
2. Поиск по заголовкам
- Добавьте поле поиска, которое фильтрует посты по вхождению текста в заголовок.
- Используйте
LIKEв SQL-запросе:1if ($search = $request->query('search')) { 2 $query->where('title', 'LIKE', "%{$search}%"); 3}
3. Бесконечная прокрутка
- Установите пакет для AJAX-пагинации:
1npm install axios - Добавьте в конец шаблона:
1<div id="posts-container"></div> 2<div id="loading" class="hidden">Загрузка...</div> 3 4<script> 5 let page = 1; 6 const loadMore = async () => { 7 page++; 8 const response = await axios.get(`/posts?page=${page}`); 9 document.getElementById('posts-container').innerHTML += response.data; 10 if (!response.data.includes('paginator')) { 11 window.removeEventListener('scroll', handleScroll); 12 } 13 }; 14 15 const handleScroll = () => { 16 if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 500) { 17 loadMore(); 18 } 19 }; 20 21 window.addEventListener('scroll', handleScroll); 22</script>
4. Статистика в сайдбаре
Добавьте блок с общей статистикой:
1<div class="bg-white p-6 rounded-lg shadow-md">
2 <h3 class="font-semibold mb-4">Статистика блога</h3>
3 <ul class="space-y-2">
4 <li>Всего постов: {{ Post::count() }}</li>
5 <li>Всего комментариев: {{ Comment::count() }}</li>
6 <li>Популярный тег: {{ Tag::withCount('posts')->orderBy('posts_count', 'desc')->first()->name }}</li>
7 </ul>
8</div>
Примечания
- Оптимизация запросов: Используйте
with()для жадной загрузки связанных данных. - Tailwind-классы: Для адаптивности применяйте grid-сетки (
md:grid-cols-2,lg:grid-cols-3).