在PHP中创build一个configuration文件

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

到目前为止,我有两个想法。

1使用variables

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

2使用常量

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

三用数据库

我将在类中使用configuration,所以我不知道哪种方式是最好的,或者如果有更好的方法。

一个简单但优雅的方法是创build一个只返回一个数组的config.php文件(或者你所说的任何东西):

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

接着:

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

使用INI文件是一个灵活而优雅的解决scheme! PHP有一个本地函数来正确处理它。 例如,可以像这样创build一个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['app_name']; // mypassword 

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

我使用@hugo_leonardo的解决scheme略微进化:

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

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

此外,如果你的应用程序configuration你需要在客户端(如一个Angular应用程序),你可以有这个config.php文件包含所有的configuration(集中在一个文件,而不是一个JavaScript和一个PHP)。 诀窍将是有另一个PHP文件,只echo客户端信息(以避免显示信息,你不想显示数据库连接string)。 叫它说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(...); 通话types。

那么 – 将数据库configuration数据存储在数据库中会有点困难 – 你不觉得吗?

但是,真的,这是一个非常炙手可热的问题,因为任何风格都是真的,而且都是偏好的问题。 就个人而言,我会去configurationvariables,而不是常量 – 通常是因为我不喜欢在全球空间的东西,除非必要。 我的代码库中的任何函数都不应该能够轻松访问我的数据库密码(除了我的数据库连接逻辑) – 所以我会在那里使用它,然后可能会摧毁它。

编辑 :回答你的评论 – 没有任何parsing机制将是最快的(ini,json等) – 但它们也不是你的应用程序的部分,你真的需要专注于优化,因为速度差异在这样的小文件上可以忽略不计。

我对这里所接受的答案感到惊讶,并且已经获得了许多赞扬。 除了Marcio Mazzucato的回答之外,没有讨论任何多种方法的相对优点/缺点。

我看到的选项是:

基于文件的机制

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

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

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

PHP代码

这为表示不同的数据结构提供了巨大的灵活性,并且(假设它是通过include或require处理的)parsing后的代码将从操作码caching中获得,从而带来性能上的好处。

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

另一方面,从代码分离configuration的主要原因之一是分离责任。 它提供了一个将附加代码注入运行时的path。

如果configuration是通过工具创build的,可以validation工具中的数据,但是没有标准函数来转义数据以embedded到PHP代码中,如HTML,URL,MySQL语句,shell命令所示。 。

序列化数据这对于less量configuration(最多约200项)相对有效,并允许使用任何PHP数据结构。 它只需要很less的代码来创build/parsing数据文件(所以你可以花费你的努力来确保文件只是用适当的授权书写)。

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

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

结构化文件

按照Marcel或JSON或XML的build议将其存储为INI文件还提供了一个简单的API来将文件映射到PHP数据结构(除XML之外,用于转义数据和创build文件),同时消除代码调用使用序列化的PHP数据的漏洞。

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

数据库存储

这是最好的考虑,你有大量的configuration,但有select性的需要什么是当前的任务 – 我很惊讶地发现,在大约150个数据项,从本地MySQL实例检索数据比反序列化一个数据文件。

OTOH它不是一个存储证书的好地方,可以连接到数据库。

执行环境

您可以在运行PHP的执行环境中设置值。

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

在客户端

我没有提到存储configuration数据的地方是在客户端。 networking开销又意味着这不能很好地适应大量的configuration。 由于最终用户对数据有控制权,因此必须以可检测到任何篡改的格式(即使用encryption签名)进行存储,并且不得包含任何因其披露而受损(即可逆encryption)的信息。

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

networking目录存储configuration信息的另一个有趣的地方是DNS / LDAP。 这将适用于less量的小部分信息 – 但是您不需要坚持第一种正常forms – 例如SPF 。

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

版本控制系统

像代码一样的configuration应该被pipe理和版本控制 – 因此直接从你的VC系统获得configuration是一个可行的解决scheme。 但是,这通常伴随着显着的性能开销,因此caching可能是明智的。

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

定义将使你的类中的所有地方不变,而不需要使用全局variables,而variables需要全局的类,我会使用DEFINE。 但是,如果在程序执行期间db参数应该改变,你可能想要使用variables。

如果你认为你会因为任何原因使用1个以上的数据库,那么使用这个variables是因为你可以改变一个参数来切换到完全不同的数据库。 即testing,自动备份等

这是我的方式。

 <?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"; 

?>

任何怀疑请评论

你可以创build一个configuration类巫女静态属性

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

那么你可以简单的使用它:

 Config::$dbHost 

有时在我的项目中,我使用devise模式SINGLETON来访问configuration数据。 使用起来非常舒适。

为什么?

例如,您的项目中有2个数据源。 而且你可以select他们的女巫启用。

  • MySQL的
  • JSON

在configuration文件的某处你select:

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

当你改变源整个应用程序shoud切换到新的数据源,工作正常,不需要更改代码。

例:

configuration:

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

单身class:

 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的值,并创build特定数据源类的新对象。 现在我们的脚本可以获取对象并对其进行操作,甚至不知道实际存在的具体实现。