Encodera

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

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

Оглавление

Модель ObjectModel

Писать insert() и update() для каждой таблицы вручную утомительно, и легко забыть про проверку значений. ObjectModel — базовый класс ядра, который представляет одну строку таблицы объектом: поля становятся свойствами, а сохранение, проверку и защиту значений класс берёт на себя. Так же устроены товары, заказы и покупатели в самом ядре.

Где лежит класс

Модели модуля хранят в папке classes. Создайте файл вручную:

modules/acmehello/
├── acmehello.php
├── classes/
│   └── AcmeReview.php
├── upgrade/
└── views/

Описание модели

<?php
// modules/acmehello/classes/AcmeReview.php
class AcmeReview extends ObjectModel
{
    public $id_product;
    public $id_customer;
    public $author;
    public $rating = 5;
    public $content;
    public $date_add;
 
    public static $definition = [
        'table' => 'acmehello_review',
        'primary' => 'id_review',
        'fields' => [
            'id_product' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
            'id_customer' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
            'author' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 100],
            'rating' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'],
            'content' => ['type' => self::TYPE_STRING, 'validate' => 'isMessage'],
            'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
        ],
    ];
}

Публичные свойства повторяют колонки таблицы. Массив $definition называет таблицу без приставки, первичный ключ и поля. Имя класса начинается с приставки модуля, чтобы не совпасть с классом ядра.

Подключение

Движок не знает о файле, пока его не подключат. Добавьте строку в начало главного файла, после проверки _PS_VERSION_:

// modules/acmehello/acmehello.php
require_once __DIR__ . '/classes/AcmeReview.php';

Теперь класс AcmeReview доступен везде, где загружен модуль.

Ключи описания поля

КлючЧто задаёт
typeТип: TYPE_INT, TYPE_BOOL, TYPE_STRING, TYPE_FLOAT, TYPE_DATE, TYPE_HTML
validateИмя метода класса Validate для проверки
requiredПоле обязательно
sizeНаибольшая длина строки

Создание записи

Перепишите метод addReview() главного класса на модель:

// modules/acmehello/acmehello.php
public function addReview(int $productId, string $author, int $rating, string $content): bool
{
    $review = new AcmeReview();
    $review->id_product = $productId;
    $review->id_customer = (int) $this->context->customer->id;
    $review->author = $author;
    $review->rating = $rating;
    $review->content = $content;
 
    return $review->add();
}

add() проверяет поля по $definition, экранирует значения и выполняет вставку. Поле date_add заполняется текущим временем само. После вставки номер новой строки лежит в $review->id.

Загрузка, изменение, удаление

$review = new AcmeReview(7);
 
if (Validate::isLoadedObject($review)) {
    $review->rating = 4;
    $review->update();
}
 
$review->delete();

Номер в конструкторе загружает строку из базы. Если строки с таким номером нет, объект создаётся пустым — поэтому результат проверяют через Validate::isLoadedObject().

МетодЧто делает
add()Вставляет новую строку
update()Сохраняет изменения
save()Сам выбирает add() или update()
delete()Удаляет строку
validateFields(false)Проверяет поля, возвращает true или false

Ошибки проверки

Если значение не проходит проверку, add() и update() бросают исключение PrestaShopException. Данные от пользователя проверяют заранее:

if (!$review->validateFields(false)) {
    return false;
}

С аргументом false метод не бросает исключение, а возвращает результат.

Списки по-прежнему через DbQuery

Модель работает с одной строкой. Список отзывов товара всё так же получают методом getReviews() из прошлого урока — запросом DbQuery.

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

В $definition добавили поле, а публичное свойство с тем же именем в классе не объявили, или наоборот. Значение молча не сохраняется или не загружается. Каждая колонка должна быть в трёх местах: в таблице, в свойствах класса и в fields.

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

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