Таблицы модуля
Настроек «ключ — значение» хватает не всегда: отзывы, заявки, историю хранят в собственной таблице. Миграций, как во фреймворках, в PrestaShop нет. Таблицу создают запросом SQL в методе install(), а изменения структуры между версиями модуля описывают в скриптах обновления.
Создание при установке
Запросы выполняет класс Db. Вынесите создание таблицы в отдельный метод главного класса:
// modules/acmehello/acmehello.php
private function createTables(): bool
{
$sql = 'CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'acmehello_review` (
`id_review` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`id_product` INT UNSIGNED NOT NULL,
`author` VARCHAR(100) NOT NULL,
`rating` TINYINT UNSIGNED NOT NULL DEFAULT 5,
`content` TEXT,
`date_add` DATETIME NOT NULL,
PRIMARY KEY (`id_review`),
KEY `id_product` (`id_product`)
) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8mb4';
return Db::getInstance()->execute($sql);
}Db::getInstance() возвращает подключение к базе магазина, execute() выполняет запрос и возвращает true или false. Константа _DB_PREFIX_ — приставка таблиц, обычно ps_, а _MYSQL_ENGINE_ — движок таблиц, обычно InnoDB.
Имена в PrestaShop принято строить так: таблица — имя модуля и сущность в единственном числе, первичный ключ — id_ плюс сущность.
Вызов из install и uninstall
// modules/acmehello/acmehello.php
public function install(): bool
{
return parent::install()
&& $this->createTables()
&& $this->registerHook('displayHome')
&& $this->registerHook('displayFooterProduct');
// остальные хуки и настройки, как раньше
}
public function uninstall(): bool
{
return Db::getInstance()->execute('DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'acmehello_review`')
&& Configuration::deleteByName('ACMEHELLO_GREETING')
&& parent::uninstall();
}Сбросьте модуль и проверьте, что таблица появилась:
php bin/console prestashop:module reset acmehelloSHOW TABLES LIKE 'ps_acmehello%';Запрос вернёт одну строку — ps_acmehello_review.
Зачем нужны скрипты обновления
Модуль версии 1.0.0 уже стоит в магазинах, и в таблице есть отзывы. В версии 1.1.0 нужна новая колонка id_customer. Менять CREATE TABLE недостаточно: install() у установленного модуля не выполняется, а сброс удалит все отзывы. Для этого и существуют скрипты обновления.
Скрипт обновления
Создайте вручную папку upgrade и файл с номером новой версии в имени:
modules/acmehello/
├── acmehello.php
├── upgrade/
│ └── upgrade-1.1.0.php
└── views/<?php
// modules/acmehello/upgrade/upgrade-1.1.0.php
if (!defined('_PS_VERSION_')) {
exit;
}
function upgrade_module_1_1_0($module)
{
return Db::getInstance()->execute(
'ALTER TABLE `' . _DB_PREFIX_ . 'acmehello_review`
ADD `id_customer` INT UNSIGNED NOT NULL DEFAULT 0 AFTER `id_product`'
);
}Имя функции — upgrade_module_ плюс версия с подчёркиваниями вместо точек. В $module приходит объект модуля: через него можно, например, подписаться на новый хук. Функция возвращает true при успехе.
Запуск обновления
- Поднимите версию в конструкторе:
$this->version = '1.1.0';. - Добавьте колонку
id_customerи вCREATE TABLE— для тех, кто ставит модуль впервые. - Запустите обновление:
php bin/console prestashop:module upgrade acmehelloДвижок сравнит версию в коде с версией, записанной в базе, и выполнит по порядку все скрипты между ними. Отзывы останутся на месте, а в таблице появится новая колонка. В панели то же происходит на странице «Менеджер модулей → Обновления».
Частая ошибка
Новую колонку добавили только в скрипт обновления и забыли про CREATE TABLE в install(). У старых магазинов всё работает, а при новой установке колонки нет, и модуль падает на первом запросе. Каждое изменение структуры вносят в два места: в скрипт обновления и в запрос создания таблицы.