在PHP中创建配置文件

时间:2013-02-07 13:37:53

标签: php configuration-files

我想为我的PHP项目创建一个配置文件,但我不确定最好的方法是什么。

到目前为止我有3个想法。

1 - 使用变量

$config['hostname'] = "localhost";
$config['dbuser'] = "dbuser";
$config['dbpassword'] = "dbpassword";
$config['dbname'] = "dbname";
$config['sitetitle'] = "sitetitle";

2-Use Const

define('DB_NAME', 'test');
define('DB_USER', 'root');
define('DB_PASSWORD', '');
define('DB_HOST', 'localhost');
define('TITLE', 'sitetitle');

3 - 使用数据库

我将在课堂上使用配置,所以我不确定哪种方式最好或者有更好的方法。

12 个答案:

答案 0 :(得分:173)

一种简单但优雅的方法是创建一个只返回数组的config.php文件(或任何你称之为的文件):

<?php

return array(
    'host' => 'localhost',
    'username' => 'root',
);

然后:

$configs = include('config.php');

答案 1 :(得分:50)

使用INI文件是一种灵活而强大的解决方案! PHP有a native function来正确处理它。例如,可以创建一个这样的INI文件:

<强> app.ini

[database]
db_name     = mydatabase
db_user     = myuser
db_password = mypassword

[application]
app_email = mailer@myapp.com
app_url   = myapp.com

所以你唯一需要做的就是打电话:

$ini = parse_ini_file('app.ini');

然后,您可以使用$ini数组轻松访问定义。

echo $ini['db_name'];     // mydatabase
echo $ini['db_user'];     // myuser
echo $ini['db_password']; // mypassword
echo $ini['app_email'];   // mailer@myapp.com

重要提示:出于安全原因,INI文件必须位于非公用文件夹中

答案 2 :(得分:23)

我使用@hugo_leonardo solution的轻微演变:

<?php

return (object) array(
    'host' => 'localhost',
    'username' => 'root',
    'pass' => 'password',
    'database' => 'db'
);

?>

这允许您在包含php时使用对象语法:$configs->host而不是$configs['host']

此外,如果您的应用程序在客户端需要配置(例如Angular应用程序),您可以将此config.php文件包含所有配置(集中在一个文件中而不是一个用于JavaScript和一个对于PHP)。然后诀窍是有另一个PHP文件,echo只有客户端信息(以避免显示您不希望显示的信息,如数据库连接字符串)。称之为get_app_info.php

<?php

    $configs = include('config.php');
    echo json_encode($configs->app_info);

?>

以上假设您的config.php包含app_info参数:

<?php

return (object) array(
    'host' => 'localhost',
    'username' => 'root',
    'pass' => 'password',
    'database' => 'db',
    'app_info' => array(
        'appName'=>"App Name",
        'appURL'=> "http://yourURL/#/"
    )
);

?>

因此,您的数据库信息保留在服务器端,但您的应用信息可以通过JavaScript访问,例如$http.get('get_app_info.php').then(...);类型的呼叫。

答案 3 :(得分:17)

我对这里接受的答案以及它所获得的赞成票数感到惊讶。除了Marcio Mazzucato的答案之外,没有讨论任何多种方法的相对优点/缺点。

我看到的选项是:

基于文件的机制

这些要求您的代码在特定位置查找以查找ini文件。这是一个难以解决的问题,并且总是在大型PHP应用程序中出现。但是,您可能需要解决问题才能找到在运行时合并/重用的PHP代码。

常见的方法是始终使用相对目录,或者从当前目录向上搜索以查找在应用程序的基本目录中专门命名的文件。

用于配置文件的常用文件格式是PHP代码,ini格式化文件,JSON,XML,YAML和序列化PHP

PHP代码

这为表示不同的数据结构提供了极大的灵活性,并且(假设它是通过include或require处理的),解析的代码将可以从操作码缓存中获得 - 从而提供性能优势。

include_path提供了一种抽象文件潜在位置的方法,而不依赖于其他代码。

另一方面,将配置与代码分离的主要原因之一是分离职责。它提供了将其他代码注入运行时的路径。

如果配置是从工具创建的,则可以验证工具中的数据,但是没有标准函数可以转义数据以嵌入到PHP代码中,如HTML,URL,MySQL语句,shell命令所存在的那样....

序列化数据 这对于少量配置(最多约200项)相对有效,并允许使用任何PHP数据结构。它只需要很少的代码来创建/解析数据文件(因此您可以花费大量精力确保文件仅使用适当的授权进行编写)。

自动处理转义写入文件的内容。

由于您可以序列化对象,因此只需通过读取配置文件(__wakeup魔术方法)就可以创建调用代码的机会。

结构化文件

将其存储为Marcel或JSON或XML建议的INI文件,还提供了一个简单的api,用于将文件映射到PHP数据结构(除了XML,以逃避数据并创建文件),同时消除使用序列化PHP数据的代码调用漏洞。

它将具有与序列化数据类似的性能特征。

数据库存储

最好考虑这一点,你有大量的配置,但选择当前任务所需的内容 - 我惊讶地发现,在大约150个数据项中,从本地MySQL检索数据更快实例而不是反序列化数据文件。

OTOH它不是存储用于连接数据库的凭据的好地方!

执行环境

您可以在PHP运行的execution environment中设置值。

这消除了PHP代码在配置的特定位置查找的任何要求。 OTOH它不能很好地扩展到大量数据,并且很难在运行时普遍改变。

在客户端

我没有提到存储配置数据的地方是客户端。网络开销再次意味着这不能很好地扩展到大量配置。并且由于最终用户可以控制数据,因此必须以可检测到任何篡改的格式(即使用加密签名)存储,并且不应包含任何因其披露而受到损害的信息(即可逆加密)。

相反,这对于存储最终用户拥有的敏感信息有很多好处 - 如果您不将其存储在服务器上,则不能从那里窃取。

网络目录 另一个存储配置信息的有趣位置是DNS / LDAP。这适用于少量小信息 - 但您不需要坚持第一范式 - 例如考虑SPF

基础设施支持缓存,复制和分发。因此,它适用于非常大的基础设施。

版本控制系统

配置与代码一样应该进行管理和版本控制 - 因此直接从VC系统获取配置是一个可行的解决方案。但通常这会带来显着的性能开销,因此缓存可能是可取的。

答案 4 :(得分:6)

嗯 - 将数据库配置数据存储在数据库中会有点困难 - 不管怎么说?

但实际上,这是一个非常自以为是的问题,因为任何风格都是有效的,而且这都是偏好问题。就个人而言,我会选择配置变量而不是常量 - 通常是因为除非必要,否则我不喜欢全局空间中的东西。我的代码库中的所有函数都不能轻松访问我的数据库密码(我的数据库连接逻辑除外) - 所以我在那里使用它然后可能会破坏它。

编辑:回答您的评论 - 解析机制中没有一个是最快的(ini,json等) - 但它们也不是您应用程序中的一部分我需要专注于优化,因为在这些小文件上速度差异可以忽略不计。

答案 5 :(得分:2)

定义将使类中的常量可用,而不需要使用全局,而变量在类中需要全局,我会使用DEFINE。但同样,如果db params在程序执行期间发生变化,您可能希望坚持使用变量。

答案 6 :(得分:2)

如果您认为由于任何原因您将使用超过1 db,请使用该变量,因为您将能够更改一个参数以切换到完全不同的db。即用于测试,自动备份等

答案 7 :(得分:2)

您可以创建一个静态属性的配置类

class Config 
{
    static $dbHost = 'localhost';
    static $dbUsername = 'user';
    static $dbPassword  = 'pass';
}

然后你可以简单地使用它:

Config::$dbHost  

有时在我的项目中,我使用设计模式SINGLETON来访问配置数据。它使用起来非常舒服。

为什么?

例如,您的项目中有2个数据源。你可以选择启用它们的女巫。

  • MySQL的
  • JS​​ON

您可以选择配置文件中的某个位置:

$dataSource = 'mysql' // or 'json'

当您将源应用程序shoud切换到新数据源时,工作正常,不需要更改代码。

示例:

配置:

class Config 
{
  // ....
  static $dataSource = 'mysql';
  / .....
}

Singleton类:

class AppConfig
{
    private static $instance;
    private $dataSource;

    private function __construct()
    {
        $this->init();
    }

    private function init()
    {
        switch (Config::$dataSource)
        {
            case 'mysql':
                $this->dataSource = new StorageMysql();
                break;
            case 'json':
                $this->dataSource = new StorageJson();
                break;
            default:
                $this->dataSource = new StorageMysql();
        }
    }

    public static function getInstance()
    {
        if (empty(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function getDataSource()
    {
        return $this->dataSource;
    }
}

...以及代码中的某个地方(例如,在某些服务类中):

$container->getItemsLoader(AppConfig::getInstance()->getDataSource()) // getItemsLoader need Object of specific data source class by dependency injection

我们可以从系统中的任何位置获取AppConfig对象,并始终获得相同的副本(感谢静态)。调用类的init()方法 在构造函数中,它只保证一次执行。 Init()正文检查 config $ dataSource的值,并创建特定数据源类的新对象。现在我们的脚本可以获取对象并对其进行操作,而不知道 甚至实际存在哪种具体实施。

答案 8 :(得分:1)

我通常最终创建一个具有数据库连接的conn.php文件。 然后我将该文件包含在需要数据库查询的所有文件中。

答案 9 :(得分:0)

这是我的方式。

<?php

define('DEBUG',0);

define('PRODUCTION',1);



#development_mode : DEBUG / PRODUCTION

$development_mode = PRODUCTION;



#Website root path for links

$app_path = 'http://192.168.0.234/dealer/';



#User interface files path

$ui_path = 'ui/';

#Image gallery path

$gallery_path = 'ui/gallery/';


$mysqlserver = "localhost";
$mysqluser = "root";
$mysqlpass = "";
$mysqldb = "dealer_plus";

&GT;

有任何疑问请发表评论

答案 10 :(得分:0)

这样的事情怎么样?

class Configuration
{

    private $config;

    
    public function __construct($configIniFilePath)
    {
        $this->config = parse_ini_file($configIniFilePath, true);
    }

    /**
     * Gets the value for the specified setting name.
     *
     * @param string $name the setting name
     * @param string $section optional, the name of the section containing the
     *     setting
     * @return string|null the value of the setting, or null if it doesn't exist
     */
    public function getConfiguration($name, $section = null)
    {
        $configValue = null;

        if ($section === null) {
            if (array_key_exists($name, $this->config)) {
                $configValue = $this->config[$name];
            }
        } else {
            if (array_key_exists($section, $this->config)) {
                $sectionSettings = $this->config[$section];
                if (array_key_exists($name, $sectionSettings)) {
                    $configValue = $sectionSettings[$name];
                }
            }
        }

        return $configValue;
    }
}

答案 11 :(得分:0)

如果我有一个像 config.conf 这样的配置文件(可以是 htttp://example.com/config.conf)

user=cacom
version = 2021608
status= true

这是我的功能:

function readFileConfig($UrlOrFilePath){

    $lines = file($UrlOrFilePath);
    $config = array();
    
    foreach ($lines as $l) {
        preg_match("/^(?P<key>.*)=(\s+)?(?P<value>.*)/", $l, $matches);
        if (isset($matches['key'])) {
            $config[trim($matches['key'])] = trim($matches['value']);
        }
    }

    return $config;
}

我们可以使用:

$urlRemote = 'http://example.com/default-config.conf';
$localConfigFile = "/home/domain/public_html/config.conf";
$localConfigFile2 = "config.conf";

print_r(readFileConfig($localConfigFile2));
print_r(readFileConfig($localConfigFile));
print_r(readFileConfig($urlRemote));