Список значений: константы кода или база данных?

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

---------------
| logs        |
|-------------|
| id          |
| idLogType   |
| message     |
| date        |
---------------

Мой вопрос касается поля "idLogType". Я знаю, что перечисление - не лучший способ справиться с этим видом поля, потому что, если я хочу добавить новые значения, у меня есть ALTER table. Поэтому я собираюсь создать список значений.

Какова ваша рекомендация для обработки списка значений?

1. Только с константами PHP?

class LogTypeValues {
  const LOGTYPE_CREATION = 1;
  const LOGTYPE_EDITION  = 2;
  const LOGTYPE_DELETION = 3;

  private $_logTypes = array();

  public function __construct() {
    $this->_logTypes[self::LOGTYPE_CREATION] = "Creation";
    $this->_logTypes[self::LOGTYPE_EDITION]  = "Edition";
    $this->_logTypes[self::LOGTYPE_DELETION] = "Deletion";
  }

  public function getId($logType) { ... }
  public function getLogType($id) { ... }
}

$request = $pdo->prepare('INSERT INTO logs SET idLogType = :idLogType, ...');
$request->execute(array('idLogType' => LogTypeValues::LOGTYPE_CREATION));

2. Только с базой данных?

------------
| logTypes |
------------
| id       |
| logType  |
------------
<?php
$request = $pdo->prepare('INSERT INTO logs SET idLogType = 1, ...');
$request->execute(array());

3. В базе данных, но также с константами PHP?

------------
| logTypes |
------------
| id       |
| logType  |
------------
class LogTypeValues {
  const LOGTYPE_CREATION = 1;
  const LOGTYPE_EDITION  = 2;
  const LOGTYPE_DELETION = 3;
}

Что вы думаете об этих 3 методах?

Ответ 1

Мое любимое решение:

Сохраняет типы журналов в базе данных:

CREATE TABLE logTypes (
    id (SMALLINT, PK)
    code VARCHAR(32) UNIQUE    
) 

Создать константы в коде

class logTypes {
    const CREATE_USER = 1;
    const EDIT_USER = 2;
    ...
}

и выберите политику синхронизации:

  • Создайте класс logTypes из DB = > код является "кешем db", если кеш не сгенерирован, проект не будет работать.
  • Создайте БД из кода = > БД полезно только для SQL-отчетов и применения SQL-функций для поиска типов журналов и т.д.

Пример:

SELECT * FROM logs JOIN logTypes USING logtype_id WHERE logType LIKE "% CREATION"

Ответ 2

Это большой вопрос - и разумные люди будут иметь разные мнения, в зависимости от вашего определения "хорошего".

Вариант 1 делает работу PHP красивой, но означает, что, когда вы хотите запросить журнал, вам нужно иметь константы в двух местах - обычно просмотрщик журналов не является тем же приложением, что и записывающее устройство. И вам нужно написать какую-то пользовательскую логику для перевода ваших целых чисел в базу данных в удобочитаемые строки. Если у вас есть несколько приложений, записывающих в базу данных журнала, сохранение констант в синхронизации между ними становится важным - если приложение 1 считает logType 1 = "Ошибка пользователя", а приложение 2 считает это "системной ошибкой", все это разваливается,

Вариант 2 сталкивается с противоположной проблемой - как ваш PHP-код "знает", что база данных считает, что logType 1 является "ошибкой пользователя"? Вы определенно не хотите иметь магические числа в кодовой базе PHP.

Вариант 3, как правило, поддерживает обе системы в синхронизации - но теперь вам нужно найти способ синхронизации базы данных с вашим файлом констант PHP. Для этого существует множество логических путей, но ни один из них не является тривиальным.

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

Ответ 3

Более или менее неструктурированные мысли:

  • Вы не должны использовать магические числа, ни в вашем коде, ни в базе данных. Таким образом, следует избегать использования типов журналов "1", "2" и т.д.
  • Вы должны использовать константы в вашем PHP-коде, и я бы дал эти константы значимым строковым значениям, а не числовым значениям.
  • Эти строковые значения могут использоваться как logType в базе данных напрямую.
  • Использование столбца ENUM для столбца logType также имеет смысл. Если вы хотите добавить типы журналов, вам нужно изменить таблицу... так что? Это не то, что должно произойти очень часто, вам нужно в любом случае изменить свой код, чтобы добавить новую константу, и в любом случае у вас должен быть код миграции схемы, что делает его тривиальным, чтобы добавить новое значение перечисления SQL.

Итак, это кажется лучшим решением для меня:

  • константы, такие как LogTypeValues::CREATION = 'creation'
  • logType столбец типа ENUM('creation', ...)
  • миграции схем для обработки сложения типов журналов

Ответ 4

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

До сих пор моим предпочтительным способом было использование опции 1, т.е. сохранение констант в исходном коде приложения (PHP/Java и т.д.). Его главное преимущество - уменьшить ненужные удары БД. Хотя некоторые из вас могут сказать, что это очень мало, но соединение с БД часто является горлом большого количества веб-приложений. Другим преимуществом является то, что он уменьшил сложность программирования.

Единственное, что я сделал в дополнение к тому, что упоминалось в этом потоке, - это добавить примечание к комментариям как в исходном коде приложения, так и в связанных столбцах таблицы БД, чтобы перекрестно ссылаться друг на друга. Таким образом, я изо всех сил старался напомнить будущим разработчикам синхронизировать эти два места, если произойдет какое-либо изменение.