在PHP Web应用程序中保存configurationvariables的最佳方法是什么?
我经常在.NET和PHP开发之间切换。 在ASP.NET网站中,我保存了web.config文件中的configuration信息(例如连接string,目录,应用程序设置),该文件受到适当的保护并且易于访问值等。
在PHP中 ,我用一个对每个variables都有静态方法的类来解决这个问题:
class webconfig { public static function defaultPageIdCode() { return 'welcome'; } }
该文件是由应用程序包含的variables访问一行:
$dp = webconfig::defaultPageIdCode();
而且由于PHP没有编译,所以很容易远程login和更改一个网站的值,所以这个解决scheme工作得很好 ,给了我这两个好处 :
- 我可以添加逻辑到一个configurationvariables,而不会中断它与应用程序的接口
- 这些configurationvariables在我的例如Eclipse,NetBeans等中显示为intellisense
但我可以想象有其他的方式,人们可以解决在PHP中保存网页configuration设置,可能有其他的优势。
特别是那些有许多PHP框架经验的人,还有其他一些保存configurationvariables的方法及其优缺点?
我决定列出所有已知的方法以及它们的优点和缺点。
我已经将这个答案标记为社区维基,因此协作更容易。
全局常量
分配:
-
define('CONFIG_DIRECTIVE', 'value');
访问:
-
$object = new MyObject(CONFIG_DIRECTIVE);
优点:
- 具有全球范围。
- 由大多数IDE自动完成。
- 有一个约定的命名约定(UPPERCASE_UNDERSCORE_SEPARATED) 。
缺点:
- 指令不能包含数组(在v7.0.0之前)。
特别提示:
- 不能重新分配。
备用语法文件
例如:XML,INI,YAML等
分配:
- 只需编辑它的特定语言的文件。 (例如,对于INI文件:
config_directive = value
。)
访问:
- configuration文件需要parsing。 (例如,对于INI:
parse_ini_file()
。)
优点:
- 最有可能有一个更适合于configuration文件的语法。
缺点:
- 访问和parsing文件的可能开销。
排列
分配:
-
$config['directive'] = 'value';
访问:
- 使用此方法访问configuration值的最简单的方法是将所需的值传递给创build时需要它们的对象,或者将它们传递给容器对象,并让它在内部传递它们。
-
$object = new MyObject($config['directive']);
-
$container = new MyContainer($config);
-
优点:
- 指令可以是数组。
缺点:
- 没有自动完成。
特别提示:
- 可变冲突可能发生。 如果这是一个问题,请适当地命名您的数组以避免它们。
类
分配:
- 有许多不同的基于类的实现。
- 静态类。
-
myCfgObj::setDirective('DIRECTIVE', 'value');
-
- 实例类。
-
myCfgObj->setDirective('DIRECTIVE', 'value');
-
- 静态类。
访问:
- 还有各种基于类的实现。
- 静态类。
-
$object = new MyObject(myCfgObj::getDirective('DIRECTIVE'));
-
- 实例类。
-
$object = new MyObject(myCfgObj->getDirective('DIRECTIVE'));
-
- 静态类。
优点:
- 可以自动加载。
缺点:
- 往往会有点冗长。
- 如果没有使用容器类,可能难以维护。
我倾向于在PHP中使用Settings静态类,这是因为
- 它具有全球范围。
- 您可以启用/禁用对受保护configuration的更改。
- 您可以在运行时的任何地方添加任何设置。
- 您可以使课程自动从文件/数据库获取公共configuration。
例:
abstract class Settings { static private $protected = array(); // For DB / passwords etc static private $public = array(); // For all public strings such as meta stuff for site public static function getProtected($key) { return isset(self::$protected[$key]) ? self::$protected[$key] : false; } public static function getPublic($key) { return isset(self::$public[$key]) ? self::$public[$key] : false; } public static function setProtected($key,$value) { self::$protected[$key] = $value; } public static function setPublic($key,$value) { self::$public[$key] = $value; } public function __get($key) {//$this->key // returns public->key return isset(self::$public[$key]) ? self::$public[$key] : false; } public function __isset($key) { return isset(self::$public[$key]); } }
然后在你的运行时,如果你先加载这个文件,然后是你的数据库configuration文件,你的数据库configuration文件看起来是这样的:
<?php Settings::setProtected('db_hostname', 'localhost'); Settings::setProtected('db_username', 'root'); Settings::setProtected('db_password', ''); Settings::setProtected('db_database', 'root'); Settings::setProtected('db_charset', 'UTF-8'); //... echo Settings::getProtected('db_hostname'); // localhost //... Settings::setPublic('config_site_title', 'MySiteTitle'); Settings::setPublic('config_site_charset', 'UTF-8'); Settings::setPublic('config_site_root', 'http://localhost/dev/');
正如你所看到的,我们有一个方法__get
,应该只允许获取公共variables,为什么我们有这样的一个例子如下:
$template = new Template(); $template->assign('settings', new Settings());
不pipe我们用这个对象作为一个静态对象的事实,值仍然应该在你现在可以做的模板中。
<html> <head> <?php echo isset($settings->config_site_title) ? $settings->config_site_title : 'Fallback Title'; ?> </head> </html>
这只允许您在初始化期间访问公共数据。
这可以得到更复杂但更系统友好的一些例子:
- 一个
loadConfig
方法来自动parsing一个configuration文件,xml,php,yaml。 - 如果您注册了
shutdown_function
,则可以使用新设置自动更新数据库。 - 您可以使用该数据库中的configuration自动填充该类。
- 你可以实现迭代器,使其与循环兼容。
- 还有更多。
这也是我迄今为止完成这项工作的最好方法。
我这样做的方式是直接将它们存储在一个array
并保存为config.php文件
<?php $config['dbname'] = "mydatabase"; $config['WebsiteName'] = "Fundoo Site"; $config['credits'] = true; $config['version'] = "4.0.4"; ?>
这是大多数PHP框架,如Wordpress等的做法。
注意:“最佳方式”从来不存在。 每个应用程序和框架都在做自己的风格。 虽然你的例子是在做的伎俩,我认为这是一个简单的configuration文件有点资源沉重。
- 你可以用Amber 指出的单个variables来做到这一点
- 你可以用数组来完成,这是最常用的方法,你总是可以轻松地编辑你的configuration文件。
- 您可以使用PHP 轻松parsing的 .ini文件来完成
编辑:
Edward请看看parse_ini_file的例子。 你可以用一个简单的命令加载.ini文件,然后你可以在你的例子中使用类中的variables。
我想有很多可能性,但最常见的方法是将文件存储为.csv,.ini,.xml等文件。 用一些小技巧你可以保护这些文件,以便没有人可以直接加载文件。
一个INI文件的例子:
;<?php die(); ?> [config1] var1 = 'value1'; var2 = 'value2'; ... [config2] ...
The ;
被认为是在ini文件中的评论。 所以当你用ini-parser读入文件时,这行会被忽略。 如果有人通过url直接访问文件, die()
函数将被执行。 这只有在INI文件使用.php这样的文件扩展名的情况下才起作用,以便服务器知道这个文件应该被执行,而不是以纯文本的forms显示。
大多数文件基本configuration存储可能的缺点是一些UTF8字符的问题。
Zend_Config是Zend-Framework的一个组件,它提供了几个存储适配器和一个易于使用的API的可能性。
在PHP中,我总是使用“.htaccess”来保护我的configuration文件(双重保护)
由于PHP能够使用OO,所以我喜欢使用“Config类”:
class Config { /** * --------------------------------- * Database - Access * --------------------------------- */ /** * @var String */ const DB_DRIVER = 'pgsql'; const DB_USER = 'postgres'; const DB_PASSWORD = 'postgres'; const DB_NAME = 'postgres'; }
Config :: DB_DRIVER很容易访问。 由于应用程序自动加载器将为您执行此操作,因此无需包含该文件。 当然,保护文件仍然需要完成。
远程login? OMG我已经陷入了时间的颠簸,到了1992年!
但严重的是,IIRC有允许asp.net(和其他语言)parsing会话数据的工具 – 这只是一个序列化的PHP数组。 我想在PHP中实现全局设置作为一种阴影会话。 即使不将configuration设置作为序列化的PHP数组存储,也可以使用自己的会话处理程序将它们映射到会话中。
就存储数据的位置而言 – 当您大概在Microsoft平台上运行时,这是一个比较棘手的问题。 很明显,您不希望为每个请求花费磁盘访问。 虽然NT做了一些磁盘caching,但它不像其他操作系统那样有效(IME)。 Memcached似乎是一个解决scheme。 它确实似乎可以从asp.net使用。
HTH
通常的路线是使用define
:
define('MYSQL_USER', 'ROOT');
并通过MYSQL_USER
在应用程序中访问它:
$user = MYSQL_USER;
但是,这种方式不支持数组。
有几种可能性:
-
你可以使用configuration文件(ini,json,xml或yaml)。 对于ini你有
parse_ini_file
,对于JSON有json_decode
(+ file_get_contents),对于YAML你必须使用外部库(searchsfYaml) -
你可以在你的脚本中包含一个包含variables或常量的configuration文件(更适合不可变的configuration,并且可以在所有的作用域中访问):
define('ROOT_DIR','\ home \ www');
$ sRootDir ='\ home \ www';
如果你是面向对象的,你可以把它包装在类中,作为属性 – 你没有每个属性的getter方法,你可以只有:
class Config { public $var1 = 'xxx'; public $var2 = 'yyy'; }
($ c = new Config(); print $ c-> var1)
要么
static class Config { public static $var1 = 'xxx'; public static $var2 = 'yyy'; }
(打印c :: $ var1)
最好是具有registry类,实现单例模式,并能够从给定的文件读取configuration。
为了可testing,我使用一个Config
类来保存实际的configuration数据和一个AppConfig
静态类,该类保存对引导程序中从应用程序范围的configuration文件(引导时注入的依赖项)加载的Config
对象的引用。 在testing环境中,我只更改Config
对象。 请参阅https://github.com/xprt64/Config