Модели и база данных
Модель — класс с запросами к базе данных. Контроллер SQL не пишет: он вызывает метод модели и получает массив. В OpenCart нет построителя запросов и объектов-записей — запросы пишут обычными строками SQL.
Где лежит
Модели витрины лежат в catalog/model/. Сквозной пример курса — отзывы о товарах, поэтому модель кладётся рядом с моделями каталога из ядра:
catalog/model/catalog/
├── product.php модель ядра
├── review.php модель ядра
└── review_summary.php новый файлСоздание модели
Создайте catalog/model/catalog/review_summary.php вручную:
// catalog/model/catalog/review_summary.php
namespace Opencart\Catalog\Model\Catalog;
class ReviewSummary extends \Opencart\System\Engine\Model
{
public function getTotal(): int
{
$query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "review`");
return (int) $query->row['total'];
}
}Метод считает строки в таблице отзывов. DB_PREFIX — приставка таблиц из config.php, обычно oc_.
Вызов из контроллера
// catalog/controller/information/hello.php
$this->load->model('catalog/review_summary');
$data['review_total'] = $this->model_catalog_review_summary->getTotal();После загрузки модель доступна как свойство: слово model и путь, где косые черты заменены подчёркиваниями. Выведите {{ review_total }} в шаблоне и откройте index.php?route=information/hello — страница покажет число отзывов.
Результат запроса
$this->db->query() возвращает объект с тремя свойствами:
| Свойство | Что в нём |
|---|---|
$query->row | Первая строка — массив |
$query->rows | Все строки — массив массивов |
$query->num_rows | Число строк |
public function getLatest(int $limit): array
{
$query = $this->db->query(
"SELECT `author`, `rating`, `text` FROM `" . DB_PREFIX . "review`
WHERE `status` = '1' ORDER BY `date_added` DESC LIMIT " . (int) $limit
);
return $query->rows;
}Метод возвращает последние опубликованные отзывы; в шаблоне их выводят циклом for.
Значения в запросе
Подстановки параметров нет. Каждое значение защищают вручную перед тем, как вставить в строку:
public function getByAuthor(string $author, int $productId): array
{
$query = $this->db->query(
"SELECT * FROM `" . DB_PREFIX . "review`
WHERE `author` = '" . $this->db->escape($author) . "'
AND `product_id` = '" . (int) $productId . "'"
);
return $query->rows;
}| Значение | Как защитить |
|---|---|
| Целое число | (int) $value |
| Дробное число | (float) $value |
| Строка | $this->db->escape($value) в кавычках |
Запись данных
INSERT, UPDATE и DELETE идут через тот же query(). После них полезны ещё два метода:
| Метод | Что возвращает |
|---|---|
$this->db->getLastId() | Идентификатор вставленной строки |
$this->db->countAffected() | Число изменённых строк |
Частая ошибка
Имя таблицы пишут без приставки: FROM review или FROM oc_review. На машине разработчика это работает, а в магазине с другой приставкой запрос падает. Всегда пишите DB_PREFIX . "review".