Мини-корзина в Laravel интернет-магазине

Мини-корзина в Laravel интернет-магазине

Разработка современного интернет-магазина требует внимания к деталям и удобству пользователей. Одним из ключевых элементов, повышающих удобство покупок, является мини-корзина. Этот компонент позволяет покупателям быстро просматривать содержимое корзины и вносить изменения без перехода на отдельную страницу. В данной статье будет рассмотрено создание мини-корзины для интернет-магазина на Laravel, популярном PHP-фреймворке.

Что такое мини-корзина и почему она важна?

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

  • Улучшение пользовательского опыта
  • Увеличение конверсии
  • Снижение количества брошенных корзин
  • Упрощение процесса покупки

Реализация мини-корзины в Laravel требует знания фреймворка, а также понимания принципов работы с сессиями и AJAX-запросами.

Подготовка проекта Laravel

Перед началом работы над мини-корзиной необходимо убедиться, что проект Laravel настроен корректно и все необходимые зависимости установлены.

Установка Laravel

Если проект еще не создан, следует установить Laravel с помощью Composer:

composer create-project --prefer-dist laravel/laravel mini-cart-project

После установки нужно перейти в директорию проекта:

cd mini-cart-project

Настройка базы данных

Для работы с корзиной потребуется настроить подключение к базе данных. В файле .env необходимо указать параметры подключения:

DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=mini_cart_db DB_USERNAME=root DB_PASSWORD=

После настройки подключения следует выполнить миграции:

php artisan migrate

Создание модели и миграции для товаров

Для работы с товарами в интернет-магазине необходимо создать соответствующую модель и миграцию.

Создание модели Product

Выполните команду для создания модели Product:

php artisan make:model Product -m

Эта команда создаст файл модели app/Models/Product.php и файл миграции в директории database/migrations.

Настройка миграции для товаров

Откройте созданный файл миграции и добавьте необходимые поля для товара:

public function up() { Schema::create('products', function (Blueprint $table) { $table->id(); $table->string('name'); $table->text('description'); $table->decimal('price', 8, 2); $table->string('image')->nullable(); $table->integer('stock')->default(0); $table->timestamps(); }); }

После внесения изменений выполните миграцию:

php artisan migrate

Реализация основной логики корзины

Теперь, когда база подготовлена, можно приступить к реализации основной логики корзины.

Создание сервиса корзины

Для управления корзиной создадим отдельный сервис. Создайте файл app/Services/CartService.php со следующим содержимым:

namespace App\Services; use Illuminate\Session\SessionManager; class CartService { const CART_KEY = 'cart'; protected $session; public function __construct(SessionManager $session) { $this->session = $session; } public function add($product, $quantity = 1) { $cart = $this->getCart(); if (isset($cart[$product->id])) { $cart[$product->id]['quantity'] += $quantity; } else { $cart[$product->id] = [ 'id' => $product->id, 'name' => $product->name, 'price' => $product->price, 'quantity' => $quantity, ]; } $this->session->put(self::CART_KEY, $cart); } public function remove($productId) { $cart = $this->getCart(); if (isset($cart[$productId])) { unset($cart[$productId]); } $this->session->put(self::CART_KEY, $cart); } public function update($productId, $quantity) { $cart = $this->getCart(); if (isset($cart[$productId])) { $cart[$productId]['quantity'] = $quantity; } $this->session->put(self::CART_KEY, $cart); } public function clear() { $this->session->forget(self::CART_KEY); } public function getCart() { return $this->session->get(self::CART_KEY, []); } public function getTotal() { $cart = $this->getCart(); $total = 0; foreach ($cart as $item) { $total += $item['price'] * $item['quantity']; } return $total; } }

Регистрация сервиса в сервис-контейнере

Для удобного использования сервиса корзины в различных частях приложения, зарегистрируем его в сервис-контейнере Laravel. Откройте файл app/Providers/AppServiceProvider.php и добавьте следующий код в метод register:

use App\Services\CartService; public function register() { $this->app->singleton(CartService::class, function ($app) { return new CartService($app['session']); }); }

Создание контроллера для управления корзиной

Следующим шагом будет создание контроллера для обработки запросов, связанных с корзиной.

Генерация контроллера

Выполните команду для создания контроллера:

php artisan make:controller CartController

Реализация методов контроллера

Откройте созданный файл app/Http/Controllers/CartController.php и добавьте следующий код:

namespace App\Http\Controllers; use App\Models\Product; use App\Services\CartService; use Illuminate\Http\Request; class CartController extends Controller { protected $cartService; public function __construct(CartService $cartService) { $this->cartService = $cartService; } public function add(Request $request) { $product = Product::findOrFail($request->input('product_id')); $quantity = $request->input('quantity', 1); $this->cartService->add($product, $quantity); return response()->json([ 'message' => 'Товар добавлен в корзину', 'cart' => $this->cartService->getCart(), 'total' => $this->cartService->getTotal(), ]); } public function remove(Request $request) { $productId = $request->input('product_id'); $this->cartService->remove($productId); return response()->json([ 'message' => 'Товар удален из корзины', 'cart' => $this->cartService->getCart(), 'total' => $this->cartService->getTotal(), ]); } public function update(Request $request) { $productId = $request->input('product_id'); $quantity = $request->input('quantity'); $this->cartService->update($productId, $quantity); return response()->json([ 'message' => 'Количество товара обновлено', 'cart' => $this->cartService->getCart(), 'total' => $this->cartService->getTotal(), ]); } public function clear() { $this->cartService->clear(); return response()->json([ 'message' => 'Корзина очищена', 'cart' => $this->cartService->getCart(), 'total' => $this->cartService->getTotal(), ]); } public function getCart() { return response()->json([ 'cart' => $this->cartService->getCart(), 'total' => $this->cartService->getTotal(), ]); } }

Настройка маршрутов для корзины

После создания контроллера необходимо настроить маршруты для обработки запросов к корзине.

Добавление маршрутов в web.php

Откройте файл routes/web.php и добавьте следующие маршруты:

use App\Http\Controllers\CartController; Route::post('/cart/add', [CartController::class, 'add'])->name('cart.add'); Route::post('/cart/remove', [CartController::class, 'remove'])->name('cart.remove'); Route::post('/cart/update', [CartController::class, 'update'])->name('cart.update'); Route::post('/cart/clear', [CartController::class, 'clear'])->name('cart.clear'); Route::get('/cart', [CartController::class, 'getCart'])->name('cart.get');

Создание интерфейса мини-корзины

Теперь, когда базовая функциональность корзины реализована, можно приступить к созданию интерфейса мини-корзины.

Создание шаблона мини-корзины

Создайте новый файл resources/views/components/mini-cart.blade.php со следующим содержимым:

<div id="mini-cart"> <h3>Корзина</h3> <ul id="cart-items"> <!-- Здесь будут отображаться товары --> </ul> <p>Итого: <span id="cart-total">0</span> руб.</p> <button id="clear-cart">Очистить корзину</button> </div>

Добавление стилей для мини-корзины

Создайте файл public/css/mini-cart.css и добавьте следующие стили:

#mini-cart { position: fixed; top: 20px; right: 20px; width: 300px; background-color: #fff; border: 1px solid #ccc; padding: 15px; box-shadow: 0 0 10px rgba(0,0,0,0.1); } #mini-cart h3 { margin-top: 0; } #cart-items { list-style-type: none; padding: 0; } #cart-items li { margin-bottom: 10px; } #clear-cart { background-color: #f44336; color: white; border: none; padding: 5px 10px; cursor: pointer; } #clear-cart:hover { background-color: #d32f2f; }

Интеграция мини-корзины в шаблон

Для отображения мини-корзины на всех страницах сайта, её нужно интегрировать в основной шаблон.

Читайте также  Значительное увеличение нестабильности в результатах поиска Google

Обновление основного шаблона

Откройте файл resources/views/layouts/app.blade.php (или создайте его, если он отсутствует) и добавьте следующий код перед закрывающим тегом </body>:

@include('components.mini-cart') <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="{{ asset('js/mini-cart.js') }}"></script> <link rel="stylesheet" href="{{ asset('css/mini-cart.css') }}">

Реализация JavaScript для работы с мини-корзиной

Для обеспечения динамического обновления мини-корзины без перезагрузки страницы необходимо реализовать JavaScript-функционал.

Создание файла mini-cart.js

Создайте файл public/js/mini-cart.js и добавьте следующий код:

$(document).ready(function
() {
function updateMiniCart() {
$.ajax({
url: '/cart',
method: 'GET',
success: function(response) {
renderMiniCart(response.cart, response.total);
}
});
}

function renderMiniCart(cart, total) {
    let cartItems = $('#cart-items');
    cartItems.empty();

    $.each(cart, function(index, item) {
        cartItems.append(`
            
  • ${item.name} - ${item.quantity} шт. x ${item.price} руб.
  • `); }); $('#cart-total').text(total); } $(document).on('click', '.add-to-cart', function(e) { e.preventDefault(); let productId = $(this).data('id'); let quantity = 1; $.ajax({ url: '/cart/add', method: 'POST', data: { product_id: productId, quantity: quantity, _token: $('meta[name="csrf-token"]').attr('content') }, success: function(response) { updateMiniCart(); alert(response.message); } }); }); $(document).on('click', '.remove-item', function() { let productId = $(this).data('id'); $.ajax({ url: '/cart/remove', method: 'POST', data: { product_id: productId, _token: $('meta[name="csrf-token"]').attr('content') }, success: function(response) { updateMiniCart(); alert(response.message); } }); }); $(document).on('change', '.update-quantity', function() { let productId = $(this).data('id'); let quantity = $(this).val(); $.ajax({ url: '/cart/update', method: 'POST', data: { product_id: productId, quantity: quantity, _token: $('meta[name="csrf-token"]').attr('content') }, success: function(response) { updateMiniCart(); } }); }); $('#clear-cart').on('click', function() { $.ajax({ url: '/cart/clear', method: 'POST', data: { _token: $('meta[name="csrf-token"]').attr('content') }, success: function(response) { updateMiniCart(); alert(response.message); } }); }); updateMiniCart(); });

    Добавление функциональности добавления товаров в корзину

    Теперь необходимо добавить возможность добавления товаров в корзину со страниц каталога или отдельных товаров.

    Обновление шаблона товара

    Откройте или создайте файл шаблона для отображения товара (например, resources/views/products/show.blade.php) и добавьте кнопку «Добавить в корзину»:

    <div class="product"> <h2>{{ $product->name }}</h2> <p>{{ $product->description }}</p> <p>Цена: {{ $product->price }} руб.</p> <button class="add-to-cart" data-id="{{ $product->id }}">Добавить в корзину</button> </div>

    Оптимизация производительности мини-корзины

    Для обеспечения быстрой работы мини-корзины можно применить несколько методов оптимизации.

    Кэширование данных корзины

    Добавьте кэширование данных корзины в сервис CartService. Обновите файл app/Services/CartService.php:

    use Illuminate\Support\Facades\Cache; class CartService { // ... public function getCart() { return Cache::remember('cart_' . $this->session->getId(), 60, function () { return $this->session->get(self::CART_KEY, []); }); } public function updateCart($cart) { $this->session->put(self::CART_KEY, $cart); Cache::put('cart_' . $this->session->getId(), $cart, 60); } // Обновите методы add, remove, update и clear, чтобы использовать updateCart вместо прямой записи в сессию }

    Отложенная загрузка мини-корзины

    Для улучшения времени загрузки страницы можно реализовать отложенную загрузку мини-корзины. Обновите файл public/js/mini-cart.js:

    $(document).ready(function() { let miniCartLoaded = false; function loadMiniCart() { if (!miniCartLoaded) { updateMiniCart(); miniCartLoaded = true; } } // Загрузка мини-корзины при наведении мыши $('#mini-cart').on('mouseenter', loadMiniCart); // Загрузка мини-корзины при прокрутке страницы $(window).on('scroll', function() { if ($(window).scrollTop() > 200) { loadMiniCart(); } }); // ... остальной код }); 

    Реализация анимации для мини-корзины

    Добавление анимации может улучшить пользовательский опыт при работе с мини-корзиной.

    Добавление CSS-анимаций

    Обновите файл public/css/mini-cart.css, добавив следующие стили:

    @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes slideIn { from { transform: translateX(100%); } to { transform: translateX(0); } } #mini-cart { animation: fadeIn 0.3s ease-out, slideIn 0.3s ease-out; } .cart-item-added { animation: fadeIn 0.3s ease-out; } .cart-item-removed { animation: fadeOut 0.3s ease-out; } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } 

    Обновление JavaScript для поддержки анимаций

    Измените функцию renderMiniCart в файле public/js/mini-cart.js:

    function renderMiniCart(cart, total) { let cartItems = $('#cart-items'); cartItems.empty(); $.each(cart, function(index, item) { let newItem = $(` 
  • ${item.name} - ${item.quantity} шт. x ${item.price} руб.
  • `); cartItems.append(newItem); setTimeout(() => newItem.removeClass('cart-item-added'), 300); }); $('#cart-total').text(total); }

    Добавление функции «Быстрый просмотр» для товаров

    Функция «Быстрый просмотр» позволяет пользователям получить более подробную информацию о товаре без перехода на отдельную страницу.

    Создание модального окна для быстрого просмотра

    Добавьте следующий HTML-код в конец файла resources/views/layouts/app.blade.php:

    <div id="quick-view-modal" class="modal"> <div class="modal-content"> <span class="close">×</span> <div id="quick-view-content"></div> </div> </div>

    Добавление стилей для модального окна

    Добавьте следующие стили в файл public/css/mini-cart.css:

    .modal { display: none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.4); } .modal-content { background-color: #fefefe; margin: 15% auto; padding: 20px; border: 1px solid #888; width: 80%; max-width: 600px; } .close { color: #aaa; float: right; font-size: 28px; font-weight: bold; cursor: pointer; } .close:hover, .close:focus { color: #000; text-decoration: none; cursor: pointer; } 

    Реализация функциональности быстрого просмотра

    Добавьте следующий код в файл public/js/mini-cart.js:

    $(document).on('click', '.quick-view', function(e) { e.preventDefault(); let productId = $(this).data('id'); $.ajax({ url: '/products/' + productId + '/quick-view', method: 'GET', success: function(response) { $('#quick-view-content').html(response); $('#quick-view-modal').show(); } }); }); $('.close').on('click', function() { $('#quick-view-modal').hide(); }); $(window).on('click', function(event) { if (event.target == $('#quick-view-modal')[0]) { $('#quick-view-modal').hide(); } }); 

    Создание контроллера и маршрута для быстрого просмотра

    Создайте новый метод в app/Http/Controllers/ProductController.php:

    public function quickView($id) { $product = Product::findOrFail($id); return view('products.quick-view', compact('product')); } 

    Добавьте новый маршрут в routes/web.php:

    Route::get('/products/{id}/quick-view', [ProductController::class, 'quickView'])->name('products.quick-view'); 

    Создание шаблона для быстрого просмотра

    Создайте новый файл resources/views/products/quick-view.blade.php:

    <div class="quick-view-product"> <h2>{{ $product->name }}</h2> <img src="{{ $product->image }}" alt="{{ $product->name }}"> <p>{{ $product->description }}</p> <p>Цена: {{ $product->price }} руб.</p> <button class="add-to-cart" data-id="{{ $product->id }}">Добавить в корзину</button> </div> 

    Реализация функции «Похожие товары»

    Функция «Похожие товары» может увеличить продажи, предлагая пользователям дополнительные товары, которые могут их заинтересовать.

    Добавление метода для получения похожих товаров

    Добавьте следующий метод в модель app/Models/Product.php:

    public function getSimilarProducts($limit = 4) { return $this->where('id', '!=', $this->id) ->inRandomOrder() ->limit($limit) ->get(); } 

    Обновление контроллера товара

    Обновите метод show в app/Http/Controllers/ProductController.php:

    public function show($id) { $product = Product::findOrFail($id); $similarProducts = $product->getSimilarProducts(); return view('products.show', compact('product', 'similarProducts')); } 

    Обновление шаблона товара

    Добавьте секцию похожих товаров в resources/views/products/show.blade.php:

    <h3>Похожие товары</h3> <div class="similar-products"> @foreach($similarProducts as $similarProduct) <div class="similar-product"> <h4>{{ $similarProduct->name }}</h4> <img src="{{ $similarProduct->image }}" alt="{{ $similarProduct->name }}"> <p>Цена: {{ $similarProduct->price }} руб.</p> <button class="add-to-cart" data-id="{{ $similarProduct->id }}">Добавить в корзину</button> <a href="{{ route('products.show', $similarProduct->id) }}" class="quick-view" data-id="{{ $similarProduct->id }}">Быстрый просмотр</a> </div> @endforeach </div> 

    Реализация функции «Часто покупаемые вместе»

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

    Читайте также  Прощание с финальной версией браузера Internet Explorer

    Создание таблицы для хранения связей между товарами

    Создайте новую миграцию:

    php artisan make:migration create_product_relations_table

    Заполните файл миграции следующим содержимым:

    public function up() { Schema::create('product_relations', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('product_id'); $table->unsignedBigInteger('related_product_id'); $table->integer('relation_count')->default(0); $table->timestamps(); $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade'); $table->foreign('related_product_id')->references('id')->on('products')->onDelete('cascade'); }); } public function down() { Schema::dropIfExists('product_relations'); }

    Выполните миграцию:

    php artisan migrate

    Обновление модели Product

    Добавьте следующий метод в модель app/Models/Product.php:

    public function getFrequentlyBoughtTogether($limit = 4) { return $this->belongsToMany(Product::class, 'product_relations', 'product_id', 'related_product_id') ->withPivot('relation_count') ->orderByDesc('pivot_relation_count') ->limit($limit) ->get(); }

    Создание сервиса для обновления связей между товарами

    Создайте новый файл app/Services/ProductRelationService.php:

    namespace App\Services; use App\Models\Product; use Illuminate\Support\Facades\DB; class ProductRelationService { public function updateRelations(array $productIds) { $combinations = $this->getCombinations($productIds); foreach ($combinations as $combination) { DB::table('product_relations') ->updateOrInsert( [ 'product_id' => $combination[0], 'related_product_id' => $combination[1] ], [ 'relation_count' => DB::raw('relation_count + 1'), 'updated_at' => now() ] ); } } private function getCombinations(array $items) { $result = []; for ($i = 0; $i < count($items); $i++) { for ($j = $i + 1; $j < count($items); $j++) { $result[] = [$items[$i], $items[$j]]; } } return $result; } }

    Обновление OrderController

    Обновите метод store в app/Http/Controllers/OrderController.php, чтобы обновлять связи между товарами после оформления заказа:

    use App\Services\ProductRelationService; public function store(Request $request, CartService $cartService, ProductRelationService $productRelationService) { // ... код создания заказа $productIds = $cartService->getCart()->pluck('id')->toArray(); $productRelationService->updateRelations($productIds); $cartService->clear(); return redirect()->route('orders.success'); }

    Обновление шаблона товара

    Добавьте секцию "Часто покупают вместе" в resources/views/products/show.blade.php:

    <h3>Часто покупают вместе</h3> <div class="frequently-bought-together"> @foreach($product->getFrequentlyBoughtTogether() as $relatedProduct) <div class="related-product"> <h4>{{ $relatedProduct->name }}</h4> <img src="{{ $relatedProduct->image }}" alt="{{ $relatedProduct->name }}"> <p>Цена: {{ $relatedProduct->price }} руб.</p> <button class="add-to-cart" data-id="{{ $relatedProduct->id }}">Добавить в корзину</button> <a href="{{ route('products.show', $relatedProduct->id) }}" class="quick-view" data-id="{{ $relatedProduct->id }}">Быстрый просмотр</a> </div> @endforeach </div>

    Реализация функции "Недавно просмотренные товары"

    Функция "Недавно просмотренные товары" помогает пользователям быстро вернуться к товарам, которые они просматривали ранее.

    Создание сервиса для работы с недавно просмотренными товарами

    Создайте новый файл app/Services/RecentlyViewedService.php:

    namespace App\Services; use Illuminate\Session\SessionManager; use App\Models\Product; class RecentlyViewedService { const RECENTLY_VIEWED_KEY = 'recently_viewed'; const MAX_ITEMS = 10; protected $session; public function __construct(SessionManager $session) { $this->session = $session; } public function addProduct($productId) { $recentlyViewed = $this->getRecentlyViewed(); if (($key = array_search($productId, $recentlyViewed)) !== false) { unset($recentlyViewed[$key]); } array_unshift($recentlyViewed, $productId); $recentlyViewed = array_slice($recentlyViewed, 0, self::MAX_ITEMS); $this->session->put(self::RECENTLY_VIEWED_KEY, $recentlyViewed); } public function getRecentlyViewed() { return $this->session->get(self::RECENTLY_VIEWED_KEY, []); } public function getRecentlyViewedProducts() { $productIds = $this->getRecentlyViewed(); return Product::whereIn('id', $productIds) ->orderByRaw("FIELD(id, " . implode(',', $productIds) . ")") ->get(); } }

    Регистрация сервиса в сервис-контейнере

    Добавьте следующий код в метод register в файле app/Providers/AppServiceProvider.php:

    use App\Services\RecentlyViewedService; $this->app->singleton(RecentlyViewedService::class, function ($app) { return new RecentlyViewedService($app['session']); });

    Обновление ProductController

    Обновите метод show в app/Http/Controllers/ProductController.php:

    use App\Services\RecentlyViewedService; public function show($id, RecentlyViewedService $recentlyViewedService) { $product = Product::findOrFail($id); $recentlyViewedService->addProduct($id); $similarProducts = $product->getSimilarProducts(); $frequentlyBoughtTogether = $product->getFrequentlyBoughtTogether(); $recentlyViewedProducts = $recentlyViewedService->getRecentlyViewedProducts()->except($id); return view('products.show', compact('product', 'similarProducts', 'frequentlyBoughtTogether', 'recentlyViewedProducts')); }

    Обновление шаблона товара

    Добавьте секцию "Недавно просмотренные товары" в resources/views/products/show.blade.php:

    <h3>Недавно просмотренные товары</h3> <div class="recently-viewed-products"> @foreach($recentlyViewedProducts as $recentProduct) <div class="recent-product"> <h4>{{ $recentProduct->name }}</h4> <img src="{{ $recentProduct->image }}" alt="{{ $recentProduct->name }}"> <p>Цена: {{ $recentProduct->price }} руб.</p> <button class="add-to-cart" data-id="{{ $recentProduct->id }}">Добавить в корзину</button> <a href="{{ route('products.show', $recentProduct->id) }}" class="quick-view" data-id="{{ $recentProduct->id }}">Быстрый просмотр</a> </div> @endforeach </div>

    Оптимизация загрузки страницы товара

    Для улучшения производительности страницы товара можно применить несколько методов оптимизации.

    Использование кэширования

    Добавьте кэширование для часто запрашиваемых данных. Обновите метод show в app/Http/Controllers/ProductController.php:

    use Illuminate\Support\Facades\Cache; public function show($id, RecentlyViewedService $recentlyViewedService) { $product = Cache::remember('product_' . $id, 3600, function () use ($id) { return Product::findOrFail($id); }); $recentlyViewedService->addProduct($id); $similarProducts = Cache::remember('similar_products_' . $id, 3600, function () use ($product) { return $product->getSimilarProducts(); }); $frequentlyBoughtTogether = Cache::remember('frequently_bought_' . $id, 3600, function () use ($product) { return $product->getFrequentlyBoughtTogether(); }); $recentlyViewedProducts = $recentlyViewedService->getRecentlyViewedProducts()->except($id); return view('products.show', compact('product', 'similarProducts', 'frequentlyBoughtTogether', 'recentlyViewedProducts')); }

    Отложенная загрузка изображений

    Используйте атрибут loading="lazy" для изображений, чтобы отложить их загрузку. Обновите все теги img в шаблонах:

    <img src="{{ $product->image }}" alt="{{ $product->name }}" loading="lazy">

    Минификация CSS и JavaScript

    Используйте Laravel Mix для минификации и объединения CSS и JavaScript файлов. Обновите файл webpack.mix.js:

    const mix = require('laravel-mix'); mix.js('resources/js/app.js', 'public/js') .sass('resources/sass/app.scss', 'public/css') .styles([ 'public/css/mini-cart.css', // другие CSS файлы ], 'public/css/all.css') .scripts([ 'public/js/mini-cart.js', // другие JS файлы ], 'public/js/all.js') .version();

    Затем обновите ссылки на CSS и JavaScript файлы в вашем основном шаблоне:

    <link rel="stylesheet" href="{{ mix('css/all.css') }}"> <script src="{{ mix('js/all.js') }}" defer></script>

    Добавление функции "Список желаний"

    Функция "Список желаний" позволяет пользователям сохранять товары, которые они хотели бы купить в будущем.

    Создание модели и миграции для списка желаний

    Создайте новую модель и миграцию:

    php artisan make:model Wishlist -m

    Заполните файл миграции следующим содержимым:

    public function up() { Schema::create('wishlists', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('user_id'); $table->unsignedBigInteger('product_id'); $table->timestamps(); $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade'); }); } public function down() { Schema::dropIfExists('wishlists'); }

    Выполните миграцию:

    php artisan migrate

    Обновление модели User

    Добавьте следующий метод в модель app/Models/User.php:

    public function wishlist() { return $this->belongsToMany(Product::class, 'wishlists')->withTimestamps(); }

    Создание контроллера для списка желаний

    Создайте новый контроллер:

    php artisan make:controller WishlistController

    Заполните файл app/Http/Controllers/WishlistController.php следующим содержимым:

    namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\Product; class WishlistController extends Controller { public function __construct() { $this->middleware('auth'); } public function index() { $wishlist = auth()->user
    
    
    ()->wishlist;
    return view('wishlist.index', compact('wishlist'));
    }
    
    public function add(Request $request)
    {
        $product = Product::findOrFail($request->input('product_id'));
        auth()->user()->wishlist()->attach($product);
        return response()->json(['message' => 'Товар добавлен в список желаний']);
    }
    
    public function remove(Request $request)
    {
        $product = Product::findOrFail($request->input('product_id'));
        auth()->user()->wishlist()->detach($product);
        return response()->json(['message' => 'Товар удален из списка желаний']);
    }
    
    }
    

    Добавление маршрутов для списка желаний

    Добавьте следующие маршруты в файл routes/web.php:

    Route::get('/wishlist', [WishlistController::class, 'index'])->name('wishlist.index'); Route::post('/wishlist/add', [WishlistController::class, 'add'])->name('wishlist.add'); Route::post('/wishlist/remove', [WishlistController::class, 'remove'])->name('wishlist.remove');

    Создание шаблона для списка желаний

    Создайте новый файл resources/views/wishlist/index.blade.php:

    @extends('layouts.app') @section('content') <h1>Список желаний</h1> @if($wishlist->count() > 0) <ul> @foreach($wishlist as $product) <li> <h3>{{ $product->name }}</h3> <img src="{{ $product->image }}" alt="{{ $product->name }}" loading="lazy"> <p>Цена: {{ $product->price }} руб.</p> <button class="add-to-cart" data-id="{{ $product->id }}">Добавить в корзину</button> <button class="remove-from-wishlist" data-id="{{ $product->id }}">Удалить из списка желаний</button> </li> @endforeach </ul> @else <p>Ваш список желаний пуст.</p> @endif @endsection @section('scripts') <script> $(document).ready(function() { $('.remove-from-wishlist').on('click', function() { let productId = $(this).data('id'); $.ajax({ url: '{{ route('wishlist.remove') }}', method: 'POST', data: { product_id: productId, _token: '{{ csrf_token() }}' }, success: function(response) { alert(response.message); location.reload(); } }); }); }); </script> @endsection

    Обновление шаблона товара

    Добавьте кнопку "Добавить в список желаний" в файл resources/views/products/show.blade.php:

    <button class="add-to-wishlist" data-id="{{ $product->id }}">Добавить в список желаний</button>

    Добавьте JavaScript для обработки добавления в список желаний:

    @section('scripts') <script> $(document).ready(function() { $('.add-to-wishlist').on('click', function() { let productId = $(this).data('id'); $.ajax({ url: '{{ route('wishlist.add') }}', method: 'POST', data: { product_id: productId, _token: '{{ csrf_token() }}' }, success: function(response) { alert(response.message); } }); }); }); </script> @endsection

    Реализация функции сравнения товаров

    Функция сравнения товаров позволяет пользователям сравнивать характеристики нескольких товаров одновременно.

    Читайте также  Значительное увеличение нестабильности в результатах поиска Google

    Создание сервиса для сравнения товаров

    Создайте новый файл app/Services/CompareService.php:

    namespace App\Services; use Illuminate\Session\SessionManager; use App\Models\Product; class CompareService { const COMPARE_KEY = 'compare_products'; const MAX_ITEMS = 4; protected $session; public function __construct(SessionManager $session) { $this->session = $session; } public function addProduct($productId) { $compareList = $this->getCompareList(); if (!in_array($productId, $compareList) && count($compareList) < self::MAX_ITEMS) { $compareList[] = $productId; $this->session->put(self::COMPARE_KEY, $compareList); } } public function removeProduct($productId) { $compareList = $this->getCompareList(); if (($key = array_search($productId, $compareList)) !== false) { unset($compareList[$key]); $this->session->put(self::COMPARE_KEY, array_values($compareList)); } } public function getCompareList() { return $this->session->get(self::COMPARE_KEY, []); } public function getCompareProducts() { $productIds = $this->getCompareList(); return Product::whereIn('id', $productIds)->get(); } public function clearCompareList() { $this->session->forget(self::COMPARE_KEY); } }

    Регистрация сервиса в сервис-контейнере

    Добавьте следующий код в метод register в файле app/Providers/AppServiceProvider.php:

    use App\Services\CompareService; $this->app->singleton(CompareService::class, function ($app) { return new CompareService($app['session']); });

    Создание контроллера для сравнения товаров

    Создайте новый контроллер:

    php artisan make:controller CompareController

    Заполните файл app/Http/Controllers/CompareController.php следующим содержимым:

    namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Services\CompareService; class CompareController extends Controller { protected $compareService; public function __construct(CompareService $compareService) { $this->compareService = $compareService; } public function index() { $products = $this->compareService->getCompareProducts(); return view('compare.index', compact('products')); } public function add(Request $request) { $this->compareService->addProduct($request->input('product_id')); return response()->json(['message' => 'Товар добавлен к сравнению']); } public function remove(Request $request) { $this->compareService->removeProduct($request->input('product_id')); return response()->json(['message' => 'Товар удален из сравнения']); } public function clear() { $this->compareService->clearCompareList(); return response()->json(['message' => 'Список сравнения очищен']); } }

    Добавление маршрутов для сравнения товаров

    Добавьте следующие маршруты в файл routes/web.php:

    Route::get('/compare', [CompareController::class, 'index'])->name('compare.index'); Route::post('/compare/add', [CompareController::class, 'add'])->name('compare.add'); Route::post('/compare/remove', [CompareController::class, 'remove'])->name('compare.remove'); Route::post('/compare/clear', [CompareController::class, 'clear'])->name('compare.clear');

    Создание шаблона для сравнения товаров

    Создайте новый файл resources/views/compare/index.blade.php:

    @extends('layouts.app') @section('content') <h1>Сравнение товаров</h1> @if($products->count() > 0) <table> <tr> <th>Характеристика</th> @foreach($products as $product) <th> {{ $product->name }} <button class="remove-from-compare" data-id="{{ $product->id }}">Удалить</button> </th> @endforeach </tr> <tr> <td>Цена</td> @foreach($products as $product) <td>{{ $product->price }} руб.</td> @endforeach </tr> <!-- Добавьте другие характеристики для сравнения --> </table> <button id="clear-compare">Очистить список сравнения</button> @else <p>Список сравнения пуст.</p> @endif @endsection @section('scripts') <script> $(document).ready(function() { $('.remove-from-compare').on('click', function() { let productId = $(this).data('id'); $.ajax({ url: '{{ route('compare.remove') }}', method: 'POST', data: { product_id: productId, _token: '{{ csrf_token() }}' }, success: function(response) { alert(response.message); location.reload(); } }); }); $('#clear-compare').on('click', function() { $.ajax({ url: '{{ route('compare.clear') }}', method: 'POST', data: { _token: '{{ csrf_token() }}' }, success: function(response) { alert(response.message); location.reload(); } }); }); }); </script> @endsection

    Обновление шаблона товара

    Добавьте кнопку "Добавить к сравнению" в файл resources/views/products/show.blade.php:

    <button class="add-to-compare" data-id="{{ $product->id }}">Добавить к сравнению</button>

    Добавьте JavaScript для обработки добавления к сравнению:

    @section('scripts') <script> $(document).ready(function() { $('.add-to-compare').on('click', function() { let productId = $(this).data('id'); $.ajax({ url: '{{ route('compare.add') }}', method: 'POST', data: { product_id: productId, _token: '{{ csrf_token() }}' }, success: function(response) { alert(response.message); } }); }); }); </script> @endsection

    Оптимизация SEO для страниц товаров

    Оптимизация SEO поможет улучшить видимость страниц товаров в поисковых системах.

    Добавление мета-тегов

    Обновите файл resources/views/products/show.blade.php, добавив мета-теги:

    @section('meta') <meta name="description" content="{{ $product->description }}"> <meta name="keywords" content="{{ $product->name }}, {{ $product->category }}"> <meta property="og:title" content="{{ $product->name }}"> <meta property="og:description" content="{{ $product->description }}"> <meta property="og:image" content="{{ $product->image }}"> <meta property="og:url" content="{{ route('products.show', $product->id) }}"> @endsection

    Использование семантической разметки

    Добавьте семантическую разметку Schema.org для товара:

    <div itemscope itemtype="http://schema.org/Product"> <h1 itemprop="name">{{ $product->name }}</h1> <img itemprop="image" src="{{ $product->image }}" alt="{{ $product->name }}"> <p itemprop="description">{{ $product->description }}</p> <div itemprop="offers" itemscope itemtype="http://schema.org/Offer"> <span itemprop="price">{{ $product->price }}</span> <meta itemprop="priceCurrency" content="RUB"> </div> </div>

    Советы по созданию сайтов