Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Таблицы модуля

Настроек «ключ — значение» хватает не всегда: отзывы, заявки, историю хранят в собственной таблице. Миграций, как во фреймворках, в 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 acmehello
SHOW 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 при успехе.

Запуск обновления

  1. Поднимите версию в конструкторе: $this->version = '1.1.0';.
  2. Добавьте колонку id_customer и в CREATE TABLE — для тех, кто ставит модуль впервые.
  3. Запустите обновление:
php bin/console prestashop:module upgrade acmehello

Движок сравнит версию в коде с версией, записанной в базе, и выполнит по порядку все скрипты между ними. Отзывы останутся на месте, а в таблице появится новая колонка. В панели то же происходит на странице «Менеджер модулей → Обновления».

Частая ошибка

Новую колонку добавили только в скрипт обновления и забыли про CREATE TABLE в install(). У старых магазинов всё работает, а при новой установке колонки нет, и модуль падает на первом запросе. Каждое изменение структуры вносят в два места: в скрипт обновления и в запрос создания таблицы.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.