Требования к базам данных¶
Важно
Не используйте в именах таблиц и полей зарезервированные слова MySQL.
Имена таблиц¶
- Таблицы, хранящие основные данные сущностей, именуются названием сущности в множественном числе. Для примера возьмём таблицу
products, которая содержит основную информацию о товарах магазина. - Таблицы, хранящие дополнительные данные сущностей или дочерние сущности, именуются по шаблону
сущность_суффикс. Добавляемый суффикс именуется во множественном числе. Для примера, таблица, содержащая цены товаров, называетсяproduct_prices. - Для понимания правил именования таблиц в более сложных случаях зависимостей таблиц друг от друга подойдёт такой пример:
products— хранит основную информацию о товарах;product_features— хранит доступные для присвоения характеристики товаров;product_feature_variants— хранит доступные для присвоения варианты характеристик товаров;product_feature_variant_descriptions— хранит мультиязычные поля вариантов характеристик товаров для каждого языка.
Важно
C каждым следующем уровнем зависимостей таблиц во множественном числе именуется только последний суффикс.
Префикс таблиц¶
При установке системы администратор задаёт префикс, который будет использован при создании всех таблиц. Префикс по-умолчанию — cscart_. В SQL-запросах, выполняемых из CS-Cart с помощью встроенных функций для работы с БД, выбранный префикс будет заменять собой плейсхолдер ?:. Таким образом, если вы упоминаете в SQL-запросе название таблицы, вы обязательно должны добавлять перед названием плейсхолдер ?:.
Короткий пример:
$products = db_get_array(
'SELECT * FROM ?:products LEFT JOIN ?:product_popularity USING(product_id)'
);
Названия полей первичных ключей¶
Исторически так сложилось, что поля и первичных, и внешних ключей именуются с префиксом названия сущности. Это означает, что, например, в таблице products поле с уникальным первичным ключом будет называться product_id. Cоветуем придерживаться этого правила при разработке модификаций CS-Cart. Даже если вы не согласны с таким правилом именования, это позволит всей кодовой базе выглядеть однотипно и однородно.
Интернационализация¶
Сущности, хранящиеся в БД, могут иметь поля, содержимое которых должно отличаться для разных языков. Например, у товаров как минимум название и описание может быть мультиязычным. Для хранения таких полей в CS-Cart используется следующий подход:
Создаётся отдельная таблица с названием
сущность_descriptions, в нашем примере этоproduct_descriptions.Таблица должна содержать поле, которое будет содержать первичные ключи сущности, для которой добавляется мультиязычность. В нашем примере это поле product_id.
Кроме того, таблица должна содержать поле, которое будет содержать код языка, для которого добавлена запись в таблицу. Обычно это поле называется lang_code и имеет тип
CHAR(2).Затем в таблицу добавляются поля, которые должны быть мультиязычными.
В нашем примере это помимо прочих product — название товара, и full_description — подробное описание товара.
Необходимость реализации логики работы с такой таблицой ложится на PHP-код, в нашем примере она вкратце сводится к следующим пунктам:
При создании нового товара учитывать, какой язык выбран в для редактирования в панели администратора (константа
DESCR_SL) — сохранять данные в таблицуproduct_descriptionsсо значением поля lang_code равным значению константыDESCR_SL.При выборке данных для отображения в клиентской части, нужно присоединять таблицу с мультиязычными данными по условию “lang_code равен выбранному пользователем языку в клиентской части (значение константы
CART_LANGUAGE)”.Пример подобного SQL-запроса:
SELECT products.*, product_descriptions.* FROM products INNER JOIN product_descriptions ON product_descriptions.product_id = products.product_id AND product_descriptions.lang_code = 'en'
Тип таблиц¶
Исторически сложилось, что для всех таблиц CS-Cart используется MyISAM. Однако ничто не мешает вам при необходимости сменить тип таблиц на InnoDB — система будет работать корректно в этом случае.
InnoDB имеет ряд преимуществ относительно MyISAM:
- внешние ограничения;
- продвинутое использование индексов в последних версиях MySQL;
- транзакции;
Примечание
Из-за особенностей внутреннего устройства запросы на запись и удаление данных в InnoDB могут занимать больше времени, чем в MyISAM.
Важно: внешние ограничения, которые вы можете добавить к таблицам в случае миграции на InnoDB, могут некорректно работать с порядком выполнения запросов изменения/удаления данных в CS-Cart. Например, при удалении категории сначала удаляется запись в таблице categories, а затем все дочерние товары и подкатегории. Это может вызвать проблемы с каскадными ограничениями ссылочной целостности вида ON UPDATE CASCADE/ON DELETE CASCADE — CS-Cart на уровне PHP-кода реализует обновление и удаление связанных сущностей.
Важно
Настоятельно рекомендуем реализовывать логику каскадного обновления/удаления данных именно в PHP-коде.
Логика в СУБД¶
Мы не рекомендуем использовать логику в БД (триггеры, хранимые процедуры и т. п.) при разработке аддонов, потому что это может вызвать проблемы с совместимостью вашего аддона и настройками MySQL на серверах клиентов - требуемые привилегии для создания триггеров и хранимых процедур могут отсутствовать. Кроме того, как и в случае с внешними ограничениями, добавляемая вами логика в БД может дублировать или конфликтовать с логикой, реализованной в PHP-коде системы.
Типы полей¶
Целочисленные поля¶
Всегда желательно выставлять у поля тот тип который не был бы избыточным.
Пример: Вы делаете флаговое поле (1,0) и решили использовать тип INT. Конечно тут нелогично использовать всю размерность поля INT — оно занимает 4 байта. Нужно использовать TINYINT (3) размером в 1 байт для экономии дискового пространтсва, выделяемого под данные. Так выборки будут шустрее.
Также не нужно забывать про флаг UNSIGNED для полей, которые являются положительными. Это в 2 раза увеличит диапазон значений.
Дополнительный числовой атрибут у типа поля вляет на отображение поэтому желательно его пропускать — MySQL сам выберет подходящую размерность. Например для TINYINT будет выбрано 3 а для SMALLINT — 5.
Описание INT полей есть на этой странице.
Сводная таблица диапазонов для INT полей, первым идёт диапазон для флага UNSIGNED:
| TINYINT | SMALLINT | MEDIUMINT | INT | BIGINT |
|---|---|---|---|---|
-128
127
|
-32768
32767
|
-8388608
8388607
|
-2147483648
2147483647
|
-9223372036854775808
9223372036854775807
|
| 0 255 | 0 65535 | 0 16777215 | 0 4294967295 | 0 18446744073709551615 |
Строковые поля¶
Данная секция касается полей которые используются как уникальные идентификаторы. В новой версии они также оптимизированы. К примеру, поле email во всех таблицах приведено к типу VARCHAR (64).
Общая рекомендация — выбирать размер поля более маленьким, чтобы избежать избычности. К примеру, нелогично ставить такому полю тип VARCHAR (255) — если есть реально ключи такой длины, впору подумывать об их сокращении.
Другие поля¶
Для ценовых полей используется тип DECIMAL (9,2).
Strict mode¶
На некоторых серверах (и последних версиях MySQL) strict-режим включен по умолчанию. Для того, чтобы таблицы соответствовали этому режиму, необходимо соблюдать несколько правил:
- Для полей с типом
TINYTEXT,TEXT,MEDIUMTEXT,LONGTEXT,BLOB,MEDIUMBLOBзапрещено использовать аттрибутDEFAULT. - Запрещено использовать аттрибут
NOT NULLбез доп. аттрибутаDEFAULT.
Плохо:
`some_field` text NOT NULL DEFAULT ''
Хорошо:
`some_field` text
Плохо:
`some_field` char(1) NOT NULL
Хорошо:
`some_field` char(1) NOT NULL DEFAULT 'A'