存储PHP应用程序设置的最佳方式?

时间:2010-03-03 02:15:01

标签: php mysql

为自定义PHP应用程序存储一组全局设置的最佳方法是什么?我正在开发一个个人项目(真正的第一个主要项目),需要一种存储键值对的方法来记录应用程序的整体设置。

要存储的东西......

  • 网站的全球名称。
  • 主题(只是变量或主题路径)

我应该把它们放在一张桌子里吗?如果是这样,从boostrap查询它们的最佳方法是什么?除了对每个所需设置进行单一查询外。


更新: 是的.ini或解析包含文件会很好,我知道如何这样做。但是我想知道将它们存储在MySQL中的最佳方法是什么。


UPDATE2: 我问这个问题的原因是我计划通过管理员界面更改许多这些设置。因此,如果您要更改网站的标题,它会立即更新,我认为最好通过SQL进行更新,因此需要在数据库中进行设置。

10 个答案:

答案 0 :(得分:19)

对于一个小而简单的网站,我只是将配置放在PHP文件中。把事情简单化。 PHP可能不会解析任何比解析PHP更快的东西。如果使用APC,则编译的字节码甚至被缓存 - 尽管然后为每个请求重新执行字节码。对于一个小的配置文件,这个字节码执行应该花费很少的时间;对于一个非常大的文件,可能需要更长的时间。

对于具有大配置的高流量站点,在APC中缓存配置数据(例如作为单个阵列)是个好主意 - 至少,您可以节省实际执行的开销config.php文件中的语句。值得注意的是,Facebook这样做。当您每秒提供多个请求时,在每个请求上访问磁盘以读取配置文件(使用parse_ini_file,XML解析器等)都是不可能的。

对于我目前的项目,我们托管了许多网站,每个网站都有自己的配置。每个站点都有一个数据库和一个配置文件;但是,确保您始终使用正确的配置文件与正确的数据库可能会成为一个令人头疼的问题。此外,更改需要在两个位置更改内容 - 数据库和配置。忘记一个或另一个总会引起问题,而且发生得太频繁了。

我们将配置移动到数据库中,因此您无法将数据库与其正确的配置分开,并且任何代码更改只需要更新数据库。来自配置表的数据也在APC中被积极缓存,因此我们很少查询它。

所以,回顾一下:

  1. 小型网站:只需使用config.php文件
  2. 非常大的网站:在APC中缓存
  3. 多个站点:在数据库中存储配置以减少管理开销;缓存在APC中以减少数据库命中

答案 1 :(得分:6)

您是否考虑将它们放在.php文件中并将其包含在您需要使用它们的页面上?为变量赋予唯一名称,以避免命名冲突。

由于您将在PHP应用程序中重复使用它们,因此这将是最理想的。如果要将数据库存储在数据库中,这也可以避免进行数据库调用。

AppSettings.php

<?php
$_SITENAME_ = 'MyWebsite';
$_THEME_ = 'Theme/Path';
?>

UPDATE:

我假设您希望这些设置可以通过网页进行编辑,并且不需要多个数据库查询,因为这些设置会发生变化,但不是经常发生?

我个人采用的一种方法是序列化AppSettings表并将其存储在XML文件中。当然,每次更新表时,表都将被重新序列化并存储在XML文件中。然后我创建了一个单独的类来解析XML文件并返回我需要的特定值。

答案 2 :(得分:2)

我们只是使用

$siteConfig['db_name'] = 'database1';
$siteConfig['site_name'] = 'Stackoverflow';

在包含的php文件中。将值放在数组中会导致名称冲突。

答案 3 :(得分:2)

我知道您希望将内容保存在mysql表中,但这可能意味着在多个位置存储所需的配置。例如,我确定你希望数据库服务器和名称存储在某个字符串中。这意味着将它们放在include或.ini文件中,因为您无法从数据库中读取它们(如何在不知道这些内容的情况下连接到数据库)。那么,您要将数据库连接信息保存在include或.ini文件中以及数据库中的其余设置中吗?我认为这是有效的,但我喜欢将所有设置保存在一个文件中(config.php或application.ini或其他)。它使维护imo更容易。

-don

答案 4 :(得分:2)

刚刚与IRC的一些人聊起这件事。我查看了在我提取一个副本的SQL转储后Wordpress如何处理这个问题。我想我会使用这个布局并重新命名列。但这个想法是......

option_id | option_name | option_value | autoload
int       | varchar     | longtext     | varchar
(PRIMARY) | (UNIQUE)    |              |

答案 5 :(得分:0)

我一般在index.php文件中设置“required”设置,所以:

<?php
session_start();
ob_start();

define('BASEPATH', $_SERVER['DOCUMENT_ROOT'].'/_setUp/siteSetup/');      // CHANGE TO THE PATH OF THE SITE.
define('URIPATH', 'http://localhost/_setUp/siteSetup/');                // CHANGE TO THE URL OF THE SITE.
define ('DEBUGGER', true);                                              // CHANGE TO FALSE TO HIDE DEBUG MESSAGES
include(BASEPATH.'system/lib/config.lib.php');
?>

并在我的配置文件中:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

// public

/* 
example:
    <img src="<?php echo IMG ?>my_image.jpg">
    http://localhost/public/images/
    <img src="http://localhost/public/images/my_image.jpg">
*/
define('CSS', URIPATH.'public/css/');                   // DEFINE DIR: css
define('IMG', URIPATH.'public/images/');                // DEFINE DIR: images   
define('JS', URIPATH.'public/scripts/');                // DEFINE DIR: scripts

// system
define('INC', BASEPATH.'system/includes/');             // DEFINE DIR: includes
define('LIB', BASEPATH.'system/lib/');                  // DEFINE DIR: lib
define('SQL', BASEPATH.'system/sql/');                  // DEFINE DIR: sql

if (DEBUGGER) {
    ini_set('log_errors',TRUE);
    ini_set("error_log", BASEPATH.'system/'."error_log.txt");
}
else {
    ini_set('log_errors',TRUE);
    ini_set("error_log", BASEPATH.'system/'."error_log.txt");
}

$db_info = array(
    'host' => 'localhost',
    'username' => 'root',
    'password' => 'root',
    'database' => 'my_db'
);


/*
to use:
    $db_info = unserialize(DB_INFO);
    echo $db_info['host'];
    echo $db_info['username'];
    echo $db_info['password'];
    echo $db_info['database'];
*/
define('DB_INFO', serialize($db_info));
?>

答案 6 :(得分:0)

一种不错的方法是通过数据库每页获取一次常用设置。保持autoload bool字段,检查是否应该使用页面加载设置。对于其他不太常见的设置,您可以通过无线方式获取它们。

如果你决定将它们全部缓存而不是为每个页面提取,你可能想要想办法通知脚本重新加载设置 - 或者你必须手动告诉它这样做,所以你改变一些后不会被旧设置卡住。

答案 7 :(得分:0)

我喜欢Microsoft.Net&#39; web.config ConfigurationManager.appSettings以及它是如何运作的。所以我模仿它,有点让它变得更好。它

  • 无需交换文件即可在任何环境中工作(我总是忘记,特别是在星期五下午4:59部署时)。
  • 自我记录函数调用的内容
  • 可以使用*
  • 处理全局设置
  <?php

    namespace Library {

    // the config depends on the environment, and the environment depends on the website url
    class Configuration {

        private static $environment;
        public static function GetEnvironment(){
            if(empty(Configuration::$environment)){
                // returns 'dev' or 'prod'
                switch($_SERVER['SERVER_NAME']){
                    case 'innitech.com':
                        Configuration::$environment = 'prod';
                    default:
                        Configuration::$environment = 'dev';
                }
            }
            return Configuration::$environment;
        }

        private const settings = [
            "dev" => [
                'dbserver'          => 'localhost',
                'database'          => 'mydb',
                'dbuser'            => 'myuser',       
                'dbpassword'        => 'mypass',       
                'dbdebug'           => false,
                'trace'             => true
            ],
            'prod' => [
                'dbserver'          => 'sql1.innitech.com',       
                'database'          => 'blahinc',
                'dbuser'            => 'proddb',
                'dbpassword'        => 'ButIWasToldiDgETaStApLer',
            ],
            '*' => [
                'adminemail'        => 'admins@innitech.com',
                'adminphone'        => '123456789',
                'dbdebug'           => false,
                'trace'             => false
            ]
        ];

        public static function Setting($name){
            return  self::setting[self::GetEnvironment()][$name] ?? 
                    self::setting['*'][$name];
        }

    }
    }
    ?>

<强>用法

$conn = new mysqli(Configuration::Setting('dbserver'), Configuration::Setting('dbuser'), Configuration::Setting('dbpassword'), Configuration::Setting('database'));

答案 8 :(得分:0)

之前提到的,是真的。我比其他人更喜欢这个,但我主要使用另一种存储配置的方式。

我从不使用数据库作为存储我的设置的地方,因为这会产生大量的数据传输,这可能会使应用程序更加不安全 - 在我看来。此外,一些应用程序主机(如亚马逊的AWS和Google的云平台)将读/写操作限制在数据库中。

因此,我主要使用这种方法:

首先,我创建一个文件config / settings.php,其中包含以下内容:

<?php
return [
    'database' => [
        'host' => 'localhost',
        'port' => 3006,
        'user' => 'username',
        'password' => // your secret password
    ],
    'application' => [
        'name' => 'Your site\'s name',
        'version' => '1.0-dev'
    ]
]

如果要在index.php文件中使用它,请在其中添加以下行:

$config = include('./config/settings.php');

我希望这可以为您或其他人添加一些信息。

答案 9 :(得分:0)

我正在使用一个将其设置存储在数据库中的系统。

简而言之,我的建议是:不要这样做!

将设置存储在数据库中意味着每当我们必须移动数据库时,例如从生产到开发,我们还必须更新所有设置,否则开发系统可能会开始发送电子邮件(确实发生过–制作头版新闻...)或与生产系统进行交互(也确实发生过-由以下人员保存)备份...)

所以,不,永远不要将配置存储在数据库中!

将设置存储在环境本地文件(开发,测试,生产)中时,您可以随意移动数据库,始终确保可以从相应环境中的文件中获取设置。 / p>

更新:进一步考虑一下,我可能会选择一个表的组合(没有服务器信息或集成信息的非致命信息,或者其他任何会杀死您的信息)。特定于环境)和一个.ini文件(或多个)。

规则是,.ini文件中的键将始终覆盖表中存储的任何内容(为防止发生上述灾难,甚至可以从任何UI将该键设置为“只读”)。

如果您想花更多的钱,甚至可以添加值类型。布尔值表示为一个复选框,带有日期选择器的日期,甚至选择带有单独选项值的框,当然,即使表可能将它们存储为字符串,整数也必须是数字。

然后,如果读取设置变慢,我会考虑使用某种形式的基于内存的缓存。