Лучшие практики работы с классом базы данных (Db Class)

Опубликовано Опубликовано в рубрике prestashop, Русская документация PrestaShop 1.6, Учебник разработчика PrestaShop 1.6

Содержание

  • Лучшие практики класса Db
    • Основы
    • Доступные методы
      • insert()
      • update()
      • delete()
      • execute()
      • query()
      • executeS()
      • getRow()
      • getValue()
      • NumRows()
      • Несколько других методов
  • Безопасность

Лучшие практики работы с классом базы данных (Db Class)

В большинстве случаев создание модуля или переопределение PrestaShop означает использование или вставку данных в базу данных. Поэтому для разработчиков важно знать, как правильно использовать основной класс БД. Помимо предоставления вам абстракции для другой потенциальной системы баз данных, класс DB предлагает несколько инструментов, облегчающих вашу жизнь.

На этой странице описываются различные методы, контекст, в которых они должны использоваться, и лучшие методы разработки.

В нижней части страницы находятся основные различия в классе DB между версиями 1.4 и 1.5+ PrestaShop.

Основы

Класс DB на самом деле состоит из двух классов:

  • Класс Db , которые можно найти в /classes/db/Db.php, абстрактный
  • Подкласс, который расширяет Db класс. В настоящее время три абстракции класса поддерживаются как подклассы: MySQL, MySQLi и PDO.
    PDO используется по умолчанию; однако, если расширение PDO не установлено на сервере, вместо этого используется расширение MySQLi. И если MySQLi также не установлен, используется MySQL.

Db — псевдо-синглтон, поскольку может быть создан вручную и его конструктор является публичным. Однако в PrestaShop рекомендуется создавать его таким образом:

$db = Db::getInstance();

В некоторых случаях вы можете столкнуться с альтернативой:

$db = Db::getInstance(_PS_USE_SQL_SLAVE_);

Если пользователь базы данных PrestaShop позволяет использовать подчиненные серверы MySQL в своей архитектуре, соединение этого последнего экземпляра может быть выполнено на подчиненных серверах.
Вы должны использовать только PS_USE_SQL_SLAVE аргумент при выполнении запросов только для чтения (SELECTSHOW, etc.), и только если они не требуют немедленного обновления результата. Если вы сделаете запрос в таблице сразу после вставки данных в ту же таблицу, вы должны выполнить этот запрос на главном сервере.

Доступные методы

insert()

Описание метода: insert($table, $data, $null_values = false, $use_cache = true, $type = Db::INSERT, $add_prefix = true).

Этот метод был создан для автоматической вставки данных в базу данных. Он должен использоваться вместо INSERT если это не сложные запросы (использование функций SQL, вложенных запросов и т. д.).

Построение каждого запроса с помощью одного метода позволяет централизовать ваши вызовы. Если однажды вам нужно выполнить определенную обработку на некоторых таблицах во время ввода данных, вы можете сделать это, перегрузив этот метод, используя переопределяющую систему PrestaShop.

Фиктивный пример:

$target = Tools::getValue('id');
$name = Tools::getValue('name');
Db::getInstance()->insert('target_table', array(
    'id_target' => (int)$target,
    'name'      => pSQL($name),
));

Запуск этого кода генерирует следующий SQL-запрос:

INSERT INTO `prefix_target_table` (`id_target`, `name`) VALUES (10'myName')

Убедитесь, что ваши данные всегда проверяются и защищаются при вставке. В нашем примере мы хотим убедиться, что у нас целое число с явным (int) и что имя защищено от SQL-инъекций благодаря методу pSQL() .

Параметры метода

Параметр

Описание

$table Имя таблицы. Префикс PrestaShop автоматически вставлен, вам не нужно его вводить.
$data Массив данных, содержащий данные для вставки, с именем в виде ключей и данных как значения
$null_values Если true, тогда значения, которые передаются как NULL, будут так и вставлены в базу данных..
$use_cache Если false, Во время этого запроса управление кэшем PrestaShop отключено. Не изменяйте этот параметр, если вы точно не знаете, что делаете.
$type Если вы хотите изменить вставку, этот параметр может принимать следующие константы: Db::INSERTDb::INSERT_IGNORE or Db::REPLACE.
$add_prefix Если false, префикс таблицы не будет автоматически добавлен к имени таблицы.

update()

Описание метода: update($table, $data, $where = '', $limit = 0, $null_values = false, $use_cache = true, $add_prefix = true)

Этот метод работает как insert() метод, но для обновления данных (UPDATE queries). Оба имеют примерно одинаковые параметры: type и эти два дополнения:

Параметр

Описание

$where Принимает обновление WHERE .
$limit Вы можете ограничить количество записей, которые вы будете обновлять.

update() не защищает ваш код от попыток взлома (инъекции SQL, недостатки XSS и нарушения CRSF). Вы должны сами защитить свои данные.
Один метод, специфичный для PrestaShop, pSQL($value): он помогает защитить вашу базу данных от SQL-инъекций.

delete()

Описание метода: delete($table, $where = '', $limit = 0, $use_cache = true, $add_prefix = true).

Этот метод эквивалентен insert() и update(), только для DELETE запросов. Вы должны использовать его по тем же причинам.

$limit параметр позволяет вам ограничить количество записей, которые вы хотите удалить. Другим преимуществом этого метода является то, что он будет использоваться системой кэширования SQL запросов PrestaShop и, следовательно, удалит затронутые запросы в кеше, отключив $use_cache в false.

Пример:

Db::getInstance()->delete('target_table''myField < 15'3);

…будет генерировать следующий запрос:

DELETE FROM `prefix_target_table` WHERE myField < 15 LIMIT 3

delete() не защищает ваш код от попыток взлома (инъекции SQL, недостатки XSS и нарушения CRSF). Вы должны сами защитить свои данные.
Один метод, специфичный для PrestaShop, pSQL($value): помогает защитить вашу базу данных от SQL-инъекций.

execute()

Описание метода: execute($sql, $use_cache = 1).

Этот метод выполняет данный SQL-запрос. Его следует использовать только для запросов «записи» (INSERTUPDATEDELETETRUNCATE, etc.), потому что он также удаляет кеш запросов (если $use_cache установлен в  false).

Пример:

$sql = 'DELETE FROM '._DB_PREFIX_.'product WHERE active = 0';
if (!Db::getInstance()->execute($sql))
    die('Erreur etc.)';

Вы должны использовать insert()update() и delete() везде , где это возможно, и используйте execute() только  если запрос становится слишком сложным
Обратите внимание, что этот метод возвращает булево (true or false),а не ресурс базы данных, который затем можно использовать

execute() не защищает ваш код от попыток взлома (инъекции SQL, недостатки XSS и нарушения CRSF). Вы должны сами защитить свои данные.
Один метод, специфичный для PrestaShop, pSQL($value): помогает защитить вашу базу данных от SQL-инъекций.

query()

Описание метода: query($sql).

Все методы классов DB, ​​которые делают SQL-запрос, используют query() как общий, низкоуровневый метод. Он делает то же самое, что и execute() метод, с двумя исключениями

  • Нет управления кешем.
  • Не возвращает булево; вместо этого возвращает ресурс базы данных, который можно использовать другими методами класса DB, например nextRow().

executeS()

Описание метода: executeS($sql, $array = true, $use_cache = 1).

Этот метод выполняет данный SQL-запрос и делает все полученные данные доступными через многомерный массив. Его следует использовать только для запросов «чтения» (SELECTSHOW, etc.). Результаты запроса кэшируются, если только $use_cache параметр не установлен в false. Второй параметр, $array(), устарел и не должен использоваться, оставьте его как true.

Пример:

$sql = 'SELECT * FROM '._DB_PREFIX_.'shop';
if ($results = Db::getInstance()->ExecuteS($sql))
    foreach ($results as $row)
        echo $row['id_shop'].' :: '.$row['name'].'<br />';

executeS() не защищает ваш код от попыток взлома (инъекции SQL, недостатки XSS и нарушения CRSF). Вы должны сами защитить свои данные.
Один метод, специфичный для PrestaShop, pSQL($value): помогает защитить вашу базу данных от SQL-инъекций.

getRow()

Описание метода: getRow($sql, $use_cache = 1).

Этот метод выполняет заданный SQL-запрос и извлекает первую строку результатов. Его следует использовать только с запросами «чтения» (SELECTSHOW, etc.). Результаты запроса кэшируются, если только $use_cache параметр не установлен в  false.

Этот метод автоматически добавляет предложение LIMIT в запрос. Будьте осторожны и не добавляйте его вручную.

Пример:

$sql = 'SELECT * FROM '._DB_PREFIX_.'shop
    WHERE id_shop = 42’;
if ($row = Db::getInstance()->getRow($sql))
    echo $row['id_shop'].' :: '.$row['name'];

getRow() не защищает ваш код от попыток взлома (инъекции SQL, недостатки XSS и нарушения CRSF). Вы должны сами защитить свои данные.
Один метод, специфичный для PrestaShop, pSQL($value): помогает защитить вашу базу данных от SQL-инъекций.

getValue()

Описание метода: getValue($sql, $use_cache = 1).

Этот метод выполняет заданный SQL-запрос и извлекает первое значение первой строки результатов. Его следует использовать только с запросами «чтения» (SELECTSHOW, etc.). Результаты запроса кэшируются, если только $use_cache параметр не установлен в  false.

Этот метод автоматически добавляет предложение LIMIT в запрос. Будьте осторожны и не добавляйте его вручную.

Пример:

$sql = 'SELECT COUNT(*) FROM '._DB_PREFIX_.'shop';
$totalShop = Db::getInstance()->getValue($sql);

getValue() не защищает ваш код от попыток взлома (инъекции SQL, недостатки XSS и нарушения CRSF). Вы должны сами защитить свои данные.
Один метод, специфичный для PrestaShop, pSQL($value): помогает защитить вашу базу данных от SQL-инъекций.

NumRows()

Этот метод кэширует и возвращает количество результатов из самого последнего SQL-запроса;

Этот метод еще не устарел, но его не рекомендуется использовать в практике. Лучше получить количество результатов, используя SELECT COUNT (*) .

Несколько других методов

  • Insert_ID():возвращает идентификатор, созданный во время последнего INSERT запроса.
  • Affected_Rows(): возвращает количество строк, затронутых последним UPDATE или DELETE запросом.
  • getMsgError(): возвращает последнее сообщение об ошибке, если запрос не выполнен.
  • getNumberError(): возвращает последний номер ошибки, если запрос не удался.

Безопасность

Обратите внимание, что ни один из вышеперечисленных методов не выполняет сам запрос. Вам нужно будет сделать это, используя pSQL() или bqSQL().

pSQL() псевдоним для Db::getInstance()->escape($string, $htmlOK);

Он имеет следующий комментарий PHPDoc:

/**
 * Очищает данные, которые будут отправлены в SQL-запрос
 *
 * @param string $string SQL data which will be injected into SQL query
 * @param bool $htmlOK Does data contain HTML code ? (optional)
 * @return string Sanitized data
 */

Он принимает строку, которая будет очищаться функцией. Если ваша строка содержит HTML-код, обязательно передайте также аргумент $htmlOK = true.

bqSQL() также могут быть использован. Обратите внимание: кроме того на ` символы, он также вызывает pSQL() после этого, но без возможности очистки HTML.