一個(gè)非常完美的讀寫ini格式的PHP配置類分享
更新時(shí)間:2015年02月12日 11:05:17 投稿:junjie
這篇文章主要介紹了一個(gè)非常完美的讀寫ini格式的PHP配置類分享,本文給出類代碼、使用例子和配置文件例子,需要的朋友可以參考下
基本滿足所有配置相關(guān)的需求。
/**
* 解析.ini格式的配置文件為一個(gè)樹形結(jié)構(gòu)的對(duì)象
* 配置文件不同section通過冒號(hào)繼承
* 默認(rèn)根據(jù)hostname確定使用的section,如果不能確定就優(yōu)先使用production
* 檢測(cè)環(huán)境的時(shí)候總是優(yōu)先檢測(cè)production,其余section按定義順序檢測(cè)
*
* @author ares@phpdr.net
*
*/
class Config {
/**
* 解析后的配置文件
*
* @var stdClass
*/
private $config;
/**
* 一個(gè)二維數(shù)組,鍵是配置文件的section
* 值是一個(gè)數(shù)組或回調(diào)函數(shù)
* 如果是數(shù)組則計(jì)算hostname是否在數(shù)組中決定是否使用該section
* 如果是回調(diào)函數(shù)通過返回值true或false來確定是否使用該section
*
* @var array
*/
private $map = array ();
/**
* section會(huì)被解析,:表示繼承
* 配置項(xiàng)中的'.'用來區(qū)分層級(jí)關(guān)系
* section中的'.'不會(huì)被解析,配置中的數(shù)組不受影響。
*
* @param string $conf
* @throws ErrorException
* @return stdClass
*/
function __construct($conf, $map) {
$config = $this->parseIni ( ( object ) parse_ini_string ( $conf, true ) );
if (array_key_exists ( 'production', $map )) {
$production = $map ['production'];
unset ( $map ['production'] );
$map = array_merge ( array (
'production' => $production ), $map );
} else {
throw new ErrorException ( 'production section not found in config' );
}
$section = 'production';
$hostname = gethostname ();
foreach ( $map as $k => $v ) {
if (is_array ( $v )) {
foreach ( $v as $v1 ) {
if ($v1 == $hostname) {
$section = $k;
break 2;
}
}
} elseif (is_callable ( $v )) {
if (true == call_user_func ( $v )) {
$section = $k;
break;
}
} else {
throw new ErrorException ( 'Wrong map value in ' . __CLASS__ );
}
}
$this->config = $config->$section;
}
/**
* 總是返回配置對(duì)象
*
* @return mixed
*/
function __get($key) {
if (isset ( $this->config->$key )) {
return $this->config->$key;
}
}
/**
* 切分
*
* @param stdClass $v
* @param string $k1
* @param mixed $v1
*/
private function split($v, $k1, $v1) {
$keys = explode ( '.', $k1 );
$last = array_pop ( $keys );
$node = $v;
foreach ( $keys as $v2 ) {
if (! isset ( $node->$v2 )) {
$node->$v2 = new stdClass ();
}
$node = $node->$v2;
}
$node->$last = $v1;
if (count ( $keys ) > 0) {
unset ( $v->$k1 );
}
}
/**
* parseIni
*
* @param object $conf
* @return stdClass
*/
private function parseIni($conf) {
$confObj = new stdClass ();
foreach ( $conf as $k => $v ) {
// 是section
if (is_array ( $v )) {
$confObj->$k = ( object ) $v;
foreach ( $v as $k1 => $v1 ) {
call_user_func ( array (
$this,
'split' ), $confObj->$k, $k1, $v1 );
}
} else {
call_user_func ( array (
$this,
'split' ), $confObj, $k, $v );
}
}
unset ( $conf );
// 處理繼承
foreach ( $confObj as $k => $v ) {
if (false !== strpos ( $k, ':' )) {
if (0 === strpos ( $k, ':' )) {
throw new ErrorException ( 'config ' . $k . ' is invalid, ':' can't be the first char' );
} elseif (1 < substr_count ( $k, ':' )) {
throw new ErrorException ( 'config ' . $k . ' is invalid, ':' can appear only once' );
} else {
$keys = explode ( ':', $k );
if (! isset ( $confObj->$keys [1] )) {
throw new ErrorException ( 'parent section ' . $keys [1] . ' doesn't exist in config file' );
} else {
if (isset ( $confObj->$keys [0] )) {
throw new ErrorException ( 'config is invalid, ' . $keys [0] . ' and ' . $k . ' conflicts' );
} else {
$confObj->$keys [0] = $this->deepCloneR ( $confObj->$keys [1] );
$this->objectMergeR ( $confObj->$keys [0], $v );
unset ( $confObj->$k );
}
}
}
}
}
return $confObj;
}
/**
* php默認(rèn)是淺克隆,函數(shù)實(shí)現(xiàn)深克隆
*
* @param object $obj
* @return object $obj
*/
private function deepCloneR($obj) {
$objClone = clone $obj;
foreach ( $objClone as $k => $v ) {
if (is_object ( $v )) {
$objClone->$k = $this->deepCloneR ( $v );
}
}
return $objClone;
}
/**
* 遞歸的合并兩個(gè)對(duì)象
*
* @param unknown $obj1
* @param unknown $obj2
*/
private function objectMergeR($obj1, $obj2) {
foreach ( $obj2 as $k => $v ) {
if (is_object ( $v ) && isset ( $obj1->$k ) && is_object ( $obj1->$k )) {
$this->objectMergeR ( $obj1->$k, $v );
} else {
$obj1->$k = $v;
}
}
}
}
簡(jiǎn)單使用:
$_ENV ['config'] = new Config ( file_get_contents ( __DIR__ . '/config.ini' ), array ( 'development' => array ( 'localhost.localdomain', 'localhost' ), 'production' => array () ) );
配置文件示例:
[product] db.default.dsn="mysql:host=127.0.0.1;dbname=default" db.default.username=root db.default.password=123456 admin.username=admin admin.password=123456 php.error_reporting=E_ALL php.display_errors=no php.log_errors=yes php.error_log=APP_PATH'/resource/log/phpError.log' php.session.save_path=APP_PATH'/resource/data/session' [development:product] db.test1.dsn="mysql:host=127.0.0.1;dbname=test1" db.test1.username=root db.test1.password=123456 php.display_errors=yes
相關(guān)文章
淺析THINKPHP的addAll支持的最大數(shù)據(jù)量
這篇文章主要介紹了THINKPHP的addAll支持的最大數(shù)據(jù)量,需要的朋友可以參考下2015-02-02
php去除數(shù)組中重復(fù)數(shù)據(jù)
去除數(shù)組中的重復(fù)數(shù)據(jù),又叫排重,本文給出的函數(shù)和php原生array_unique的區(qū)別在于array_unique要求是字符串,而本函數(shù)可以是數(shù)組和對(duì)象2014-11-11
ThinkPHP表單自動(dòng)提交驗(yàn)證實(shí)例教程
這篇文章主要介紹了ThinkPHP表單自動(dòng)提交驗(yàn)證實(shí)例教程,非常有實(shí)用價(jià)值,需要的朋友可以參考下2014-07-07
微信公眾號(hào)支付之坑:調(diào)用支付jsapi缺少參數(shù) timeStamp等錯(cuò)誤解決方法
這段時(shí)間一直比較忙,一忙起來真感覺自己就只是一臺(tái)掙錢的機(jī)器了(說的好像能掙到多少錢似的,呵呵);這會(huì)難得有點(diǎn)兒空閑時(shí)間,想把前段時(shí)間開發(fā)微信公眾號(hào)支付遇到問題及解決方法跟大家分享下,這些“暗坑”能不掉就不掉吧,要不然關(guān)鍵時(shí)刻出問題,真是讓人急的焦頭爛額2016-01-01
PHP中如何使用session實(shí)現(xiàn)保存用戶登錄信息
這篇文章主要給大家介紹在php中是如何使用session實(shí)現(xiàn)保存用戶登錄信息的,涉及到php session 用戶登錄等一些知識(shí)點(diǎn),使用session保存用戶登錄信息要比cookie安全很多。感興趣的朋友一起學(xué)習(xí)吧2015-10-10

