Encodera

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

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

Оглавление

Запросы: Db и DbQuery

Таблица отзывов создана, теперь её нужно наполнять и читать. Запросы к базе выполняет класс Db, а запрос на выборку удобно собирать построителем DbQuery — он сам добавляет приставку таблиц и расставляет части запроса по местам.

Вставка строки

Добавьте в главный класс метод, который сохраняет отзыв:

// modules/acmehello/acmehello.php
public function addReview(int $productId, string $author, int $rating, string $content): bool
{
    return Db::getInstance()->insert('acmehello_review', [
        'id_product' => $productId,
        'author' => pSQL($author),
        'rating' => $rating,
        'content' => pSQL($content),
        'date_add' => date('Y-m-d H:i:s'),
    ]);
}

Имя таблицы пишут без приставки — insert() добавит её сам. Функция pSQL() экранирует строку, чтобы кавычка в тексте не сломала запрос.

Чтобы было что читать, добавьте пару строк прямо в базу:

INSERT INTO ps_acmehello_review (id_product, author, rating, content, date_add)
VALUES (1, 'Anna', 5, 'Great product', NOW()), (1, 'Boris', 4, 'Good', NOW());

Чтение

// modules/acmehello/acmehello.php
public function getReviews(int $productId): array
{
    $query = new DbQuery();
    $query->select('r.id_review, r.author, r.rating, r.content, r.date_add')
        ->from('acmehello_review', 'r')
        ->where('r.id_product = ' . $productId)
        ->orderBy('r.date_add DESC')
        ->limit((int) Configuration::get('ACMEHELLO_LIMIT'));
 
    return Db::getInstance()->executeS($query) ?: [];
}

from() принимает имя таблицы без приставки и короткий псевдоним. executeS() возвращает массив строк, каждая строка — массив «колонка — значение».

Использование в хуке

Замените в обработчике хука массив-заглушку на вызов метода:

// modules/acmehello/acmehello.php
public function hookDisplayFooterProduct(array $params): string
{
    $this->context->smarty->assign([
        'reviews' => $this->getReviews((int) Tools::getValue('id_product')),
    ]);
 
    return $this->fetch('module:acmehello/views/templates/hook/product-reviews.tpl');
}

Откройте на витрине товар с номером 1: в блоке отзывов теперь строки из базы. У остальных товаров — «Отзывов пока нет».

Методы чтения

МетодЧто возвращает
executeS($query)Все строки
getRow($query)Первую строку
getValue($query)Первое значение первой строки
execute($sql)true или false — для запросов без результата

Средняя оценка товара — одно значение, для него подходит getValue():

$query = new DbQuery();
$query->select('AVG(r.rating)')
    ->from('acmehello_review', 'r')
    ->where('r.id_product = ' . (int) $productId);
 
$average = round((float) Db::getInstance()->getValue($query), 1);

Методы DbQuery

МетодЧасть запроса
select('a.id, a.name')Колонки
from('table', 'a')Таблица и псевдоним
leftJoin('product', 'p', 'p.id_product = a.id_product')Соединение
where('a.active = 1')Условие; несколько вызовов соединяются через AND
groupBy('a.id_product')Группировка
orderBy('a.date_add DESC')Сортировка
limit(10, 20)Количество и смещение

Обновление и удаление

$db = Db::getInstance();
 
$db->update('acmehello_review', ['rating' => 4], 'id_review = ' . (int) $reviewId);
$db->delete('acmehello_review', 'id_review = ' . (int) $reviewId);
 
$newId = (int) $db->Insert_ID();

Третий аргумент update() и второй аргумент delete() — условие WHERE. Insert_ID() возвращает номер последней вставленной строки.

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

Значение из запроса, вставленное в условие напрямую, — это SQL-инъекция: ->where('id_product = ' . Tools::getValue('id_product')). Класс Db не подставляет параметры за вас. Каждое число приводите через (int), каждую строку пропускайте через pSQL() и берите в кавычки: "author = '" . pSQL($author) . "'".

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

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