代码之家  ›  专栏  ›  技术社区  ›  Urda Gael Fraiteur

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

  •  11
  • Urda Gael Fraiteur  · 技术社区  · 14 年前

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

    要存储的内容…

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

    我应该把它们放在一张桌子上吗?如果是这样,从助推器中查询它们的最佳方法是什么?除了为每个所需的设置执行单个查询之外。


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


    更新2: 我之所以要求这样做,也是因为我计划通过管理员界面更改许多这些设置。因此,如果您要更改站点的标题,它将立即更新,我认为最好通过SQL进行更新,因此需要在数据库中进行设置。

    10 回复  |  直到 6 年前
        1
  •  6
  •   Omar    14 年前

    你有没有想过把它们放在 .php 把它放在你需要使用的页面上?为变量指定唯一的名称,以避免命名冲突。

    由于您将在您的PHP应用程序中反复使用它们,所以这将是最理想的方法。如果要将数据库存储在数据库中,这也避免了进行数据库调用的需要。

    AppSettings.php

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

    更新:

    我假设您希望通过网页编辑这些设置,并且不希望多个数据库查询,因为这些设置将更改,但不会太频繁?

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

        2
  •  19
  •   Frank Farmer    14 年前

    对于一个小而简单的站点,我只需要将config放到一个php文件中。保持简单。PHP可能不会比它解析PHP更快地解析任何东西。如果使用APC,编译后的字节码甚至会被缓存——尽管字节码随后会针对每个请求重新执行。对于一个小的配置文件,这个字节码执行应该花费很少的时间;对于一个非常大的文件,可能需要更长的时间。

    对于具有大配置的高流量站点,在APC中缓存配置数据(例如作为单个数组)是一个好主意——至少,您可以节省 正在执行 config.php文件中的语句。值得注意的是,Facebook做到了这一点。当您每秒处理许多请求时,点击磁盘读取每个请求的配置文件(使用parse-ini-u文件、XML解析器等)是不可能的。

    对于我当前的项目,我们托管许多站点,每个站点都有自己的配置。每个站点都有一个数据库和一个配置文件;但是,确保始终将正确的配置文件与正确的数据库一起使用可能会成为一个难题。此外,更改需要在两个地方进行更改——db和config。忘记一个或另一个总是造成问题,而且发生得太频繁了。

    我们将配置移到数据库中,这样就不可能将数据库从正确的配置中分离出来,任何代码更改都只需要更新数据库。来自config表的数据也被积极地缓存在apc中,因此我们很少查询它。

    因此,回顾一下:

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

    我们只是使用

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

    在包含的PHP文件中。将值放入数组有助于解决名称冲突。

        4
  •  2
  •   Don Dickinson    14 年前

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

    -唐

        5
  •  2
  •   Urda Gael Fraiteur    14 年前

    刚和IRC上的几个人聊完这件事。我查看了WordPress是如何处理这个问题的,在我提取了一个SQL副本的转储之后。我想我将使用这个布局并对列重命名一点。但想法是…

    option_id | option_name | option_value | autoload
    int       | varchar     | longtext     | varchar
    (PRIMARY) | (UNIQUE)    |              |
    
        6
  •  0
  •   cdnicoll    14 年前

    我通常在index.php文件中设置“必需”设置,以便:

    <?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));
    ?>
    
        7
  •  0
  •   casraf    14 年前

    一个不错的方法是通过数据库,每页获取一次常用的设置。有点像 autoload 用于检查是否应将设置与页面一起加载的布尔字段。对于其他更不常用的提取设置,您可以在空中提取它们。

    如果您决定将它们全部缓存,而不是为每个页面提取数据,那么您可能需要考虑一种方法来通知脚本重新加载设置——或者您必须手动告诉它这样做,这样在更改某些设置之后就不会陷入旧设置的困境。

        8
  •  0
  •   Jordy Deweer    6 年前

    前面提到的是真的。我更喜欢这一个,但我主要使用另一种方法来存储我的配置。

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

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

    首先,我创建了一个文件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
  •   toddmo    6 年前

    我喜欢Microsoft.NET的 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'));
    
        10
  •  0
  •   Erk    6 年前

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

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

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

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

    当您将设置存储在一个文件中时,您可以在本地环境(dev、test、prod)中随意移动数据库,始终确保将在相应的环境中从文件中提取设置。

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

    规则是.ini文件中的一个键总是覆盖表中存储的任何内容(为了防止上述灾难,甚至可能使该键从任何UI“只读”)。

    如果您想获得额外的幻想,您甚至可以添加值类型;布尔值表示为一个复选框,日期与日期选择器,甚至选择框与分隔的选项值,当然,ints将必须是数字,即使表可能存储为字符串。

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