分享一个完善的读写ini格式的PHP配置类

分类:PHP_Python| 发布:佚名| 查看:318 | 发表时间:2015/8/10

基本满足所有配置相关的需求。

001/**
002 * 解析.ini格式的配置文件为一个树形结构的对象
003 * 配置文件不同section通过冒号继承
004 * 默认根据hostname确定使用的section,如果不能确定就优先使用production
005 * 检测环境的时候总是优先检测production,其余section按定义顺序检测
006 *
007 * @author ares@phpdr.net
008 *   
009 */
010class Config {
011 /**
012 * 解析后的配置文件
013 *
014 * @var stdClass
015 */
016 private $config;
017 /**
018 * 一个二维数组,键是配置文件的section
019 * 值是一个数组或回调函数
020 * 如果是数组则计算hostname是否在数组中决定是否使用该section
021 * 如果是回调函数通过返回值true或false来确定是否使用该section
022 *
023 * @var array
024 */
025 private $map = array ();
026  
027 /**
028 * section会被解析,:表示继承
029 * 配置项中的'.'用来区分层级关系
030 * section中的'.'不会被解析,配置中的数组不受影响。
031 *
032 * @param string $conf    
033 * @throws ErrorException
034 * @return stdClass
035 */
036 function __construct($conf, $map) {
037 $config = $this->parseIni ( ( object ) parse_ini_string ( $conf, true ) );
038 if (array_key_exists ( 'production', $map )) {
039  $production = $map ['production'];
040  unset ( $map ['production'] );
041  $map = array_merge ( array (
042   'production' => $production ), $map );
043 } else {
044  throw new ErrorException ( 'production section not found in config' );
045 }
046 $section = 'production';
047 $hostname = gethostname ();
048 foreach ( $map as $k => $v ) {
049  if (is_array ( $v )) {
050  foreach ( $v as $v1 ) {
051   if ($v1 == $hostname) {
052   $section = $k;
053   break 2;
054   }
055  }
056  } elseif (is_callable ( $v )) {
057  if (true == call_user_func ( $v )) {
058   $section = $k;
059   break;
060  }
061  } else {
062  throw new ErrorException ( 'Wrong map value in ' . __CLASS__ );
063  }
064 }
065 $this->config = $config->$section;
066 }
067  
068 /**
069 * 总是返回配置对象
070 *
071 * @return mixed
072 */
073 function __get($key) {
074 if (isset ( $this->config->$key )) {
075  return $this->config->$key;
076 }
077 }
078  
079 /**
080 * 切分
081 *
082 * @param stdClass $v    
083 * @param string $k1    
084 * @param mixed $v1    
085 */
086 private function split($v, $k1, $v1) {
087 $keys = explode ( '.', $k1 );
088 $last = array_pop ( $keys );
089 $node = $v;
090 foreach ( $keys as $v2 ) {
091  if (! isset ( $node->$v2 )) {
092  $node->$v2 = new stdClass ();
093  }
094  $node = $node->$v2;
095 }
096 $node->$last = $v1;
097 if (count ( $keys ) > 0) {
098  unset ( $v->$k1 );
099 }
100 }
101  
102 /**
103 * parseIni
104 *
105 * @param object $conf    
106 * @return stdClass
107 */
108 private function parseIni($conf) {
109 $confObj = new stdClass ();
110 foreach ( $conf as $k => $v ) {
111  // 是section
112  if (is_array ( $v )) {
113  $confObj->$k = ( object ) $v;
114  foreach ( $v as $k1 => $v1 ) {
115   call_user_func ( array (
116    $this,
117    'split' ), $confObj->$k, $k1, $v1 );
118  }
119  } else {
120  call_user_func ( array (
121   $this,
122   'split' ), $confObj, $k, $v );
123  }
124 }
125 unset ( $conf );
126 // 处理继承
127 foreach ( $confObj as $k => $v ) {
128  if (false !== strpos ( $k, ':' )) {
129  if (0 === strpos ( $k, ':' )) {
130   throw new ErrorException ( 'config ' . $k . ' is invalid, ':' can't be the first char' );
131  } elseif (1 < substr_count ( $k, ':' )) {
132   throw new ErrorException ( 'config ' . $k . ' is invalid, ':' can appear only once' );
133  } else {
134   $keys = explode ( ':', $k );
135   if (! isset ( $confObj->$keys [1] )) {
136   throw new ErrorException ( 'parent section ' . $keys [1] . ' doesn't exist in config file' );
137   } else {
138   if (isset ( $confObj->$keys [0] )) {
139    throw new ErrorException ( 'config is invalid, ' . $keys [0] . ' and ' . $k . ' conflicts' );
140   } else {
141    $confObj->$keys [0] = $this->deepCloneR ( $confObj->$keys [1] );
142    $this->objectMergeR ( $confObj->$keys [0], $v );
143    unset ( $confObj->$k );
144   }
145   }
146  }
147  }
148 }
149 return $confObj;
150 }
151  
152 /**
153 * php默认是浅克隆,函数实现深克隆
154 *
155 * @param object $obj    
156 * @return object $obj
157 */
158 private function deepCloneR($obj) {
159 $objClone = clone $obj;
160 foreach ( $objClone as $k => $v ) {
161  if (is_object ( $v )) {
162  $objClone->$k = $this->deepCloneR ( $v );
163  }
164 }
165 return $objClone;
166 }
167  
168 /**
169 * 递归的合并两个对象
170 *
171 * @param unknown $obj1    
172 * @param unknown $obj2    
173 */ private function objectMergeR($obj1, $obj2) {
174 foreach ( $obj2 as $k => $v ) {
175  if (is_object ( $v ) && isset ( $obj1->$k ) && is_object ( $obj1->$k )) {
176  $this->objectMergeR ( $obj1->$k, $v );
177  } else {
178  $obj1->$k = $v;
179  }
180 }
181 }
182}

简单使用:

1$_ENV ['config'] = new Config ( file_get_contents ( __DIR__ . '/config.ini' ), array (
2 'development' => array (
3  'localhost.localdomain',
4  'localhost'
5 ),
6 'production' => array ()
7) );

配置文件示例:

01[product]
02db.default.dsn="mysql:host=127.0.0.1;dbname=default"
03db.default.username=root
04db.default.password=123456
05 
06admin.username=admin
07admin.password=123456
08 
09php.error_reporting=E_ALL
10php.display_errors=no
11php.log_errors=yes
12php.error_log=APP_PATH'/resource/log/phpError.log'
13php.session.save_path=APP_PATH'/resource/data/session'
14 
15[development:product]
16db.test1.dsn="mysql:host=127.0.0.1;dbname=test1"
17db.test1.username=root
18db.test1.password=123456
19php.display_errors=yes

 

365据说看到好文章不转的人,服务器容易宕机
原创文章如转载,请注明:转载自郑州网建-前端开发 http://camnpr.com/
本文链接:http://camnpr.com/php-python/2093.html