Best way to store a PHP App's Settings?

前端 未结 10 1815
南笙
南笙 2020-12-08 11:26

What is the best approach to storing a group of global settings for a custom PHP application? I am working on a personal project (first major one really), and need a method

相关标签:
10条回答
  • 2020-12-08 12:06

    I liked Microsoft.Net's web.config ConfigurationManager.appSettings and how that worked. So I mimicked it and kinda made it better. It

    • Works in any environment without having to swap files (which I always forget, especially when deploying on Friday at 4:59 p.m.)
    • Is self documenting on what the function call is
    • Can handle global settings with *
      <?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];
            }
    
        }
        }
        ?>
    

    Usage

    $conn = new mysqli(Configuration::Setting('dbserver'), Configuration::Setting('dbuser'), Configuration::Setting('dbpassword'), Configuration::Setting('database'));
    
    0 讨论(0)
  • 2020-12-08 12:06

    A decent approach would be to fetch commonly used settings once per page, via database. Something like keeping a autoload bool field that checks whether the setting should be loaded with the page. For other, much less commonly fetched settings, you can fetch them over the air.

    If you decide to cache them all instead of fetching for every page, you might want to think of a way to notify the script to reload the settings -- or you'd have to manually tell it to do so, so you wouldn't get stuck with old settings after changing some.

    0 讨论(0)
  • 2020-12-08 12:10

    For a single, small, simple site, I'd just put config in a PHP file. Keep it simple. PHP probably doesn't parse anything faster than it parses PHP. If you use APC, the compiled bytecode is even cached -- although the bytecode is then re-executed for every request. For a small config file, this bytecode execution should take very little time; for a very large file, it might take a bit longer.

    For high-traffic sites with large configs, caching your config data in APC (e.g. as a single array) is a good idea -- at the very least, you save the overhead of actually executing the statements in your config.php file. Notably, facebook does this. When you're serving many requests per second, hitting the disk to read a config file (using parse_ini_file, an XML parser, etc.) on every request is out of the question.

    For my current project, we host many sites, each with their own config. Each site had both a database and a config file; however, making sure you're always using the right config file with the right database can become a headache. Additionally, changes would require changing things in two places -- the db and the config. Forgetting one or the other always caused problems, and it happened far too frequently.

    We moved the config into the database, so that you can't possibly separate a db from it's correct config, and any code changes only require updating the database. The data from the config table is also aggressively cached in APC, so we query it rarely.

    So, to recap:

    1. Small site: just use a config.php file
    2. Very large site: cache in APC
    3. Multiple sites: store config in database to reduce administration overhead; cache in APC to reduce database hits
    0 讨论(0)
  • 2020-12-08 12:10

    I generally within my index.php file set up the "required" settings so:

    <?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');
    ?>
    

    and within my config file:

    <?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));
    ?>
    
    0 讨论(0)
  • 2020-12-08 12:11

    i understand you want to keep things in a mysql table, however, that likely means storing required configuration in multiple places. for example, i'm sure you'll want the database server and name stored in a string somewhere. that means putting those in an include or .ini file since you can't read them from a database (how can you connect to the database without knowing those things). so, you'd be keeping the db connection info in an include or .ini file and the rest of the settings in the database? that works, i suppose, but i like to keep all of the settings in one file (config.php or application.ini or whatever). it makes it easier to maintain imo.

    -don

    0 讨论(0)
  • 2020-12-08 12:18

    I'm working with a system that does store its settings in the database.

    My advice in short: Do not do it!

    Storing the settings in the database means, whenever we have to move the database, e.g. from production to development, we also have to update all the settings, or the dev system might start sending e-mails (did happen--made front-page news...) or interact with production systems (also happened--saved by backups...)

    So, no, never store the configuration in the database!

    When you store the settings in a file, local to the environment (dev, test, prod) you can move the database around at your leisure, always assured the settings will be picked up from the file in the respective environment.

    Update: Giving it some more thought I'd probably go for a combination of a table (non-lethal information without server info or integration info or anything else that will kill you if it isn't environment specific) and a .ini-file (or several).

    The rule would be that a key in a .ini-file would always override anything stored in the table (to prevent above disasters, maybe even make that key "read-only" from any UI).

    If you want to get extra fancy you might even add value types; boolean represented as a checkbox, dates with a date selector, even select boxes with separated option values, and of course ints that would have to be numbers even if the table might store them as strings.

    Then I'd look into using some form of memory-based caching if reading the settings got slow.

    0 讨论(0)
提交回复
热议问题