值列表:代码常量或数据库?

时间:2014-06-20 09:45:41

标签: php database key-value-store

我想知道价值管理清单是否有良好的做法。 例如,我有一个数据库表日志如下:

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

我的问题是关于字段" idLogType"。我知道枚举不是处理这种字段的好方法,因为如果我想添加新值,我必须改变表格。所以我要创建一个值列表。

您对处理值列表的建议是什么?

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;
}

你对这三种方法有什么看法?

4 个答案:

答案 0 :(得分:4)

我最喜欢的解决方案是:

在数据库中存储日志类型:

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

在代码中创建常量

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

并选择同步政策:

  • 从DB =&gt;创建logTypes类代码是“db的缓存”,如果没有生成缓存,项目将无法正常工作
  • 从代码中创建数据库=&gt; DB仅对sql报告有用,并且将SQL功能应用于logtypes搜索等...

示例:

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

答案 1 :(得分:2)

这是一个很好的问题 - 合理的人会有不同的意见,这取决于你对&#34; good&#34;的定义。

选项1使PHP工作得很好,但意味着当你想查询日志时,需要将常量放在两个地方 - 通常,日志查看器与日志编写器不是同一个应用程序。而且你必须编写一些自定义逻辑来将数据库中的整数转换为人类可读的字符串。如果你有多个应用程序写入日志数据库,保持它们之间的常量同步变得很重要 - 如果应用程序1认为logType 1 =&#34;用户错误&#34;而应用程序2认为它的系统错误&#34;,整个事情就崩溃了。

选项2面临着相反的问题 - 您的PHP代码&#34;如何知道&#34;数据库认为logType 1是&#34;用户错误&#34;?你绝对不希望PHP代码库中有魔术数字。

选项3从概念上保持两个系统同步 - 但现在你必须找到一种方法来使数据库与PHP常量文件同步。有很多逻辑路线可以做到这一点 - 但没有一个是微不足道的。

由于我对于爬进的bug很懒惰和偏执,我通常不会使用整数 - 相反,PHP代码会从常量文件中将表示日志类型的字符串写入数据库。

答案 2 :(得分:2)

我也曾几次面对类似的情况。显然,上面提到的所有选项都有利弊,我也没有想到。这就是我找到这个帖子的原因。

到目前为止,我首选的方法是使用选项1,即仅在应用程序的源代码(PHP / Java等)中存储常量。它的主要优点是减少不必要的DB命中。虽然有些人可能会说它非常小,但数据库连接通常是许多Web应用程序的瓶颈。另一个优点是它降低了编程的复杂性。

除了本主题中提到的内容之外,我唯一做的就是在应用程序源代码和相关的DB表列中的注释中添加注释,以便相互交叉引用。这样,我尽力提醒未来的开发人员,如果发生任何变化,请同步这两个地方。

答案 3 :(得分:1)

或多或少的非结构化想法:

  • 您不应该在您的代码或数据库中使用幻数。因此,具有日志类型&#34; 1&#34;,&#34; 2&#34;等应该避免。
  • 你应该在PHP代码中使用常量,并且我给这些常量提供有意义的字符串值,而不是数值。
  • 这些字符串值可以直接用作数据库中的logType
  • 因此ENUM列使用logType也非常有意义。如果要添加日志类型,则需要更改表...那么什么?这不是经常发生的事情,你需要改变你的代码来添加一个新的常量,并且你应该有适当的模式迁移代码,这使得添加新的SQL枚举值变得微不足道。

所以,这对我来说似乎是最好的解决方案:

  • LogTypeValues::CREATION = 'creation'
  • 等常量 {li> logType类型ENUM('creation', ...)
  • 用于处理日志类型添加的模式迁移