/ PHP

PHP程序配置文件(最佳?)实践

最原始的方式

写php程序时会直接把数据库、缓存的连接信息放在config.php文件里。这样做有两个弊端,1.在开发调试时必须先把连接信息改成本地的,要提交代码时再改回远程的,麻烦,也容易遗漏。2.开发人员可以直接看到线上数据库的连接地址、账号、密码,不安全。

怎么办?

线上运行PHP程序时通常需要一个Http服务器,例如apache、nginx。以nginx为例,在配置文件中可以通过fastcgi_param指令来给PHP传递变量

fastcgi_param DB_HOST "192.168.1.1";

这样就可以在PHP代码里通过$_SERVER[‘DB_HOST’]来获取到对应的值。

所以开发环境和线上环境只要配好nginx的配置,就可以实现不改代码执行程序了。

更进一步,可以传递一个标示当前环境的变量,例如

fastcgi_param CODE_ENV "production";

然后在程序里可以根据$_SERVER[‘CODE_ENV’]的不同来执行一些不同的逻辑(比如开发环境会打印所有错误信息而线上环境不显示)

这样完美了吗?

并没有,在实际应用中发现有两个问题:1.如果这个PHP程序不仅仅提供web服务,还提供了cli工具(例如数据库升级脚本),这个时候nginx传递的变量就过不来了。2.貌似不支持传递数组变量。

解决思路

要同时支持web和cli,通过nginx配置传变量已经行不通了,那能不能走php自己的配置呢?

于是在php.ini的末尾加上如下配置:

[userconf] userconf.db_host=127.0.0.1 userconf.db_name=test

重启php-fpm之后,发现通过ini_get(‘userconf.db_host’)取到的数据是空,于是详细查看了php的文档,发现对于自定义的配置项,需要通过get_cfg_var()函数来获得。经过测试,在web和cli模式下,通过get_cfg_var(‘userconf.db_host’)可以拿到正确的值。

再优化

但这个方案还是有弊端:1.修改配置需要重启php-fpm。2.虽然php.ini里面支持数组的数据,但是还是不够灵活,最好是能直接用php配置。

所以我们可以在php.ini里面只配置一个配置目录的路径,这个目录下放置各个程序的配置文件,php程序先从php.ini获取到这个目录的路径,再从这个目录下读取php格式的配置文件。示例代码:

$path = get_cfg_var('userconf.dir'); $conf = include($path . '/test.php');

这样配置文件是每次访问都会重新读取,变更时不需要重启php-fpm;而且不同的站点只要选择不同的配置文件名,就可以在一台服务器上共存。

但这样还是有一个问题没有解决,那就是无法在同一台服务器上部署两个相同的站点,不过这个场景也不多,不解决也没关系。