Требования к базам данных¶
Важно
Не используйте в именах таблиц и полей зарезервированные слова 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'