Мини-корзина в 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; }

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

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

Читайте также  Влияние обновления дат на ранжирование старого контента

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

Откройте файл 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> 

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

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

    Читайте также  Прогноз годового дохода рекламной площадки Telegram - 10 миллиардов рублей.

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

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

    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

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

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

    Читайте также  Как называется уникальный корабль московских спасателей?

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

    Создайте новый файл 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>

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