存储全局站点首选项[PHP / MySQL]

时间:2010-02-11 14:29:04

标签: php mysql database preferences entity-attribute-value

有人可以推荐存储常规网站偏好的最佳做法吗?例如,如果脚本未设置一个默认页面标题,或者要在内容框中显示的特色项目数,或者在上载图片时系统应该制作的缩略图大小列表。集中这些值具有明显的好处,即允许人们轻松改变可能在许多页面上使用的首选项。

我的默认方法是将这些首选项作为属性/值对放在* gulp * EAV表中。

这个表不大可能变得很大,所以我不太担心性能。我的架构的其余部分是关系型的。它确实会让一些该死的丑陋查询:

$sql = "SELECT name, value FROM preferences"
.    " WHERE name = 'picture_sizes'"
.    " OR name = 'num_picture_fields'"
.    " OR name = 'server_path_to_http'"
.    " OR name = 'picture_directory'";
$query = mysql_query($sql);
if(!$query) {
    echo "Oops! ".mysql_error();
}
while($results = mysql_fetch_assoc($query)) {
    $pref[$results['name']] = $results['value'];
}

有人能提出更好的方法吗?

7 个答案:

答案 0 :(得分:8)

在我的应用程序中,我使用这种结构:

CREATE TABLE `general_settings` (
  `setting_key` varchar(255) NOT NULL,
  `setting_group` varchar(255) NOT NULL DEFAULT 'general',
  `setting_label` varchar(255) DEFAULT NULL,
  `setting_type` enum('text','integer','float','textarea','select','radio','checkbox') NOT NULL DEFAULT 'text',
  `setting_value` text NOT NULL,
  `setting_options` varchar(255) DEFAULT NULL,
  `setting_weight` int(11) DEFAULT '0',
  PRIMARY KEY (`setting_key`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

示例数据:

mysql> select * from general_settings;
+-----------------------------+---------------+------------------------------+--------------+-------------------------------+---------------------------------------+----------------+
| setting_key                 | setting_group | setting_label                | setting_type | setting_value                 | setting_options                       | setting_weight |
+-----------------------------+---------------+------------------------------+--------------+-------------------------------+---------------------------------------+----------------+
| website_name                | website       | Website Name                 | text         | s:6:"DeenTV";                 | NULL                                  |              1 | 

我将序列化值存储在setting_value列中。我从wordpress方式获得了这个技巧来保存数据库中的设置。

setting_options列用于selectradiocheckbox setting_type。它将包含序列化的数组值。在admin中,此值将显示为选项,因此管理员可以选择其中一个。

由于我使用CodeIgniter,因此我有一个模型可以从特定的setting_key获取单个值,因此它非常易于使用。

答案 1 :(得分:2)

我认为这是一个完全可以接受的结构,特别是对于像你这样的少量配置。

您还可以将这些设置存储在.ini文件中,然后拨打parse_ini_file。如果您需要比INI允许的更多灵活性(例如:嵌套数组等),那么您可以将它们全部放入.php文件中并包含它。

如果你仍然想要使用数据库中的配置,那么(假设只有少数几行)也许只需一次读取所有记录并缓存它。

$config = array();
$result = mysql_query("SELECT * FROM config");
while ($row = mysql_fetch_assoc($result)) {
    $config[$row['name']] = $row['value'];
}

答案 2 :(得分:2)

你看起来很好看。

如果您担心自己的查询看起来很难看,可以尝试稍微清理一下SQL。

以下是您在问题中提供的更清晰的查询版本:

SELECT name, value FROM preferences
WHERE name IN ('picture_sizes','num_picture_fields','server_path_to_http','picture_directory')";

或者也许创建一个存储函数来返回一个偏好值;例如,使用这样的存储函数:

DELIMITER $$

CREATE FUNCTION `getPreference` (p_name VARCHAR(50)) RETURNS VARCHAR(200)
BEGIN
  RETURN (SELECT `value` FROM preferences WHERE `name` = p_name);
END $$

DELIMITER ;

您可以使用以下查询获取您的偏好设置:

SELECT getPreference('server_path_to_http')

你没有硬编码(显然)你牺牲了一点速度。但是,如果您计划启用“站点管理员”来更改默认首选项 - 您应该将它们保留在数据库中。

答案 3 :(得分:1)

我认为使用包含文件将为您节省一些麻烦 - 特别是如果您想要将数组包含为您的变量之一。如果您计划动态更改配置变量,那么也许最好对其进行db,但如果它保持相对静态,我会建议使用'config.php'文件

答案 4 :(得分:1)

许多应用程序,包括例如Wordpress,使用序列化和反序列化。它允许您创建一个非常简单的表结构,甚至可能只有一个记录(例如,对于您的项目使用site_id)。

数组中的所有(很多很多)变量都被序列化为字符串并存储。然后获取并反序列化回数组结构。

临: 你不必事先计划完美的配置结构,做很多ALTER TABLE的东西。

缺点: 您无法通过SQL搜索序列化数组结构。

命令:

string serialize  ( mixed $value  )
mixed unserialize  ( string $str  )

也适用于您的对象。反序列化对象可以使用__wakeup()方法。

答案 5 :(得分:0)

只需创建一个configure类,并将所需的每个值存储在类的变量中。

在所有正在调用的文件中包含此类。

您现在可以在所有文件中访问此类,并通过在所有函数中声明global来访问configure类。

希望得到这个帮助。

答案 6 :(得分:0)

我解决这个问题的方法是创建一个表,每个配置变量都有一个单独的列,就像使用任何其他数据集一样,并设置主键,使表不能包含多个一个条目。我这样做是通过将主键设置为只有一个允许值的枚举,如下所示:

CREATE TABLE IF NOT EXISTS `global_config` (
  `row_limiter` enum('onlyOneRowAllowed') NOT NULL DEFAULT 'onlyOneRowAllowed',#only one possible value
  `someconfigvar` int(10) UNSIGNED NOT NULL DEFAULT 0,
  `someotherconfigvar` varchar(32) DEFAULT 'whatever',
  PRIMARY KEY(`row_limiter`)#primary key on a field which only allows one possible value
) ENGINE = InnoDB;

INSERT IGNORE INTO `global_config` () VALUES ();#to ensure our one row exists

完成此设置后,可以使用简单的UPDATE语句修改任何值,使用简单的SELECT语句查找,连接到其他表以用于更复杂的查询等。

这种方法的另一个好处是它允许正确的数据类型,外键以及所有其他与正确的数据库设计一起确保数据库完整性的东西。 (只需确保将外键设置为ON DELETE SET NULL或ON DELETE RESTRICT而不是ON DELETE CASCADE)。例如,假设您的一个配置变量是网站主要管理员的用户ID,您可以使用以下内容展开示例:

CREATE TABLE IF NOT EXISTS `global_config` (
  `row_limiter` enum('onlyOneRowAllowed') NOT NULL DEFAULT 'onlyOneRowAllowed',
  `someconfigvar` int(10) UNSIGNED NOT NULL DEFAULT 0,
  `someotherconfigvar` varchar(32) DEFAULT 'whatever',
  `primary_admin_id` bigint(20) UNSIGNED NOT NULL,
  PRIMARY KEY(`row_limiter`),
  FOREIGN KEY(`primary_admin_id`) REFERENCES `users`(`user_id`) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE = InnoDB;

INSERT IGNORE INTO `global_config` (`primary_admin_id`) VALUES (1);#assuming your DB is set up that the initial user created is also the admin

这确保您始终具有有效的配置,即使配置变量需要引用数据库中的其他实体。