Сегодняшний урок будет довольно скучным, потому что ничего нового вы из него не узнаете.
Будет всё то же самое, что и прежде: пишем миграцию, модели, контроллеры, странички в админке и само оформление заказов на публичном сайте.
Собственно, когда вы понимаете как работает Vesp, вся работа с ним становится вот такой предсказуемой рутиной. Есть новая задача - сел и сделал! Никаких сюрпризов, борьбы и превозмогания.
Каталог товаров вывели и оформили, теперь нужно сделать корзину, куда будем их складывать.
Авторизации на сайте у нас нет, значит корзина будет храниться не в базе данных, а на клиенте. Для долговременного хранения мы используем localStorage, а для текущего состояния - Vuex.
Vuex - это глобальное хранилище нашего приложения, к которому может обращаться любой компонент Vue. Он позволяет им обмениваться данными, даже если они находятся на разных страницах и ничего друг о друге не знают.
Можно сказать, что это такая "внутренняя сессия" приложения, только очень функциональная. Вот сегодня, на примере работы с корзиной, мы её и освоим.
Сегодня мы оформим страницы товаров и категорий.
Думаю, на этом работа по выводу каталога будет окончена и можно будет переключиться на корзину и оформление заказов.
Как вы, наверное, помните, мы написали компонент для вывода всех товаров и теперь можем его легко расширить для вывода товаров конкретной категории.
Делается это добавлением нового параметра, и при его наличии, изменением адреса запроса на контроллер товаров категории, который мы написали в прошлом уроке.
На прошлом уроке мы доработали наш вывод товаров, добавив к нему выборку картинок.
Теперь нужно сделать вывод категорий и страниц товаров. Учитывая общепринятые нормы, мы не можем выводить их все просто по id
, поэтому давайте добавим колонки alias
обеим моделям.
У категорий все alias
будут уникальны, а у товаров они будут уникальны в каждой категории.
Alias
становится обязательным полем для модели, то есть он всегда должен быть заполнен. Это значит, что колонка в таблице не будет nullable
, а поэтому при создании уникального индекса по этой колонки в ней уже должны быть уникальные значения, или получим ошибку.
Если бы наш магазин уже был в работе, то нам нужно было бы добавить новую колонку, затем прописать уникальные значения в каждую модель, и только потом добавлять индекс unique()
. Но сейчас мы можем смело удалить все записи из БД, а после запуска миграции создать их снова через запуск seed
.
На прошлом уроке мы сделали товарам галереи, теперь нужно вывести из них файлы.
Как правило, в магазинах принято выводить первую картинку галереи в качестве титульной. То есть, показывать её во всех скписках товаров, включая админку.
С этого мы и начнём - с присоединения первого изображения товара аж четырьмя способами, и выберем из них самый оптимальный.
На прошлом уроке вы сгенерировали и вывели наши товары на сайте.
Выглядит это пока простенько, поэтому довайте добавим нашим товарам картинки. То есть, напишем галерею товара.
Этот урок доступен бесплатно в рекламных целях, вдруг кто-то почитает и захочет оплатить доступ и к предыдущим?
У Vesp предусмотрена система работы с файлами, стандартная модель и таблица для них. Нам нужно будет только использовать эту систему для загрузки картинок товарам.
Я предлагаю создать новую модель ProductFile
, которая свяжет товары с файлами. Делаем composer db:create ProductFiles
и редактируем новую миграцию:
<?php
use Illuminate\Database\Schema\Blueprint;
use Vesp\Services\Migration;
final class ProductFiles extends Migration
{
public function up(): void
{
$this->schema->create(
'product_files',
function (Blueprint $table) {
// Связи с родительскими моделями
$table->foreignId('product_id')
->constrained('products')->cascadeOnDelete();
$table->foreignId('file_id')
->constrained('files')->cascadeOnDelete();
// Порядок вывода картинок в галерее
$table->unsignedInteger('rank')->default(0);
// Картинки можно будет отключать
$table->boolean('active')->default(true)->index();
// Назначаем первичный ключ из 2х колонок
$table->primary(['product_id', 'file_id']);
}
);
}
public function down(): void
{
$this->schema->drop('product_files');
}
}
Ну что, модели созданы, контроллеры отлажены, пора бы и вывести товары на нашем сайте.
Для удобной работы предлагаю использовать очень известную библиотеку Faker, которая позволит нам нагенерировать нужное количество товаров и категорий без лишних сложностей.
Устаналиваем fakerphp/faker
зависимостью для разработки, на рабочем окружении она не будет нужна:
composer require fakerphp/faker --dev
Затем создаём новый seed файл в core/db/seeds/Products.php
Возможно вы обратили внимание, что на прошлом уроке мы добавили в таблицы категорий и товаров строку поиска, но она не работает?
Это потому, что никто не написал сам функционал поиска в контроллерах. Мы просто расширили базовый ModelController
и больше ничего не меняли.
Помимо этого в категориях мы указали колонку для вывода общего количества товаров - и она тоже пуста, по той же причине.
Предлагаю сегодня доработать наши контроллеры и добавить недостающие функции.
Ну что, друзья! Начинается самое интересное - реальная разработка нашего магазина.
Сегодня напишем базовые миграции, модели и контроллеры админки. А потом создадим и страницы для работы со всем этим.
Перед начал разработки я провёл генеральную уборку кода пакета vesp/vesp и добавил новые команды в composer
, так что советую пересоздать проект заново, базу данных и настройки .env
можно не трогать, только обновить исходники.
По ходу дела я постараюсь прикинуть, сколько времени у меня уходит на те или иные операции.
Честно говоря, не думал, что только знакомство с системой затянется аж на 10 заметок. Мне-то оно всё давно привычно и понятно, а вот когда пытаешься внятно об этом рассказать...
В общем, сегодня мы заканчиваем вводную часть, и дальше будет настоящая работа по постройке магазина VespShop.
На нужно посмотреть, какие еще компоненты я написал для удобной работы на Vesp, и начнём с переключателя языка - vesp-change-locale
(по клику откроется GIFка)
Следующий важный компонент админки - модальные окна для создания и редактирования моделей.
Vesp-modal
расширяет компонент из BootstrapVue, принимает всего его параметры и добавляет отправку формы с данными.
Редактируемые данные передаются через v-model
, и если в них указан первичный ключ (по умолчанию поле id
, но можно настроить и другой), то форма отправится методом PATCH
(редактирование), а если нет, то PUT
(создание).
Содержимое формы вставляется в слот #form-fields
, а сами формы я предлагаю хранить отдельно от модальных окон, для удобства. Давайте разберём форму работы с пользователями.
Продолжаем наше знакомство с админкой Vesp.
Опираясь на свой опыт работы в MODX я постарался повторить примерную логику работы и здесь, для чего были написаны основные компоненты админки. Под капотом они используют BootstrapVue, но в будущем могут быть переписаны и на другую систему, при этом основной код страниц менять не придётся.
Для примера давайте разберёмся как именно работает раздел с пользователями