一個(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; } } } }
簡單使用:
$_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)文章
thinkPHP5項(xiàng)目中實(shí)現(xiàn)QQ第三方登錄功能
這篇文章主要介紹了thinkPHP5項(xiàng)目中實(shí)現(xiàn)QQ第三方登錄功能,結(jié)合實(shí)例形式較為詳細(xì)的分析了修改QQ登陸接口并整合進(jìn)thinkPHP5項(xiàng)目中的具體步驟與相關(guān)操作技巧,需要的朋友可以參考下2017-10-10php實(shí)現(xiàn)文件下載簡單示例(代碼實(shí)現(xiàn)文件下載)
這篇文章主要介紹了php實(shí)現(xiàn)文件下載簡單示例,需要的朋友可以參考下2014-03-03Smarty最簡單實(shí)現(xiàn)列表奇偶變色的方法
這篇文章主要介紹了Smarty最簡單實(shí)現(xiàn)列表奇偶變色的方法,實(shí)例分析了Smarty屬性與方法的相關(guān)使用技巧,需要的朋友可以參考下2015-07-07laravel-admin利用ModelTree實(shí)現(xiàn)對(duì)分類信息的管理
這篇文章主要介紹了laravel-admin利用ModelTree實(shí)現(xiàn)對(duì)分類信息的管理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01PHP傳值到不同頁面的三種常見方式及php和html之間傳值問題
這篇文章主要介紹了PHP傳值到不同頁面的三種常見方式及php和html之間傳值問題的相關(guān)資料,需要的朋友可以參考下2015-11-11php對(duì)數(shù)字進(jìn)行萬、億單位的轉(zhuǎn)化
在本篇文章里小編給大家整理了一篇關(guān)于php對(duì)數(shù)字進(jìn)行萬、億單位的轉(zhuǎn)化,有需要的朋友們可以跟著學(xué)習(xí)下。2021-08-08php中用加號(hào)與用array_merge合并數(shù)組的區(qū)別深入分析
本篇文章是對(duì)php中用加號(hào)與用array_merge合并數(shù)組的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06