一个非常完美的读写ini格式的PHP配置类分享

2025-05-29 0 44

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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183
/**

* 解析.ini格式的配置文件为一个树形结构的对象

* 配置文件不同section通过冒号继承

* 默认根据hostname确定使用的section,如果不能确定就优先使用production

* 检测环境的时候总是优先检测production,其余section按定义顺序检测

*

* @author ares@phpdr.net

*

*/

class Config {

/**

* 解析后的配置文件

*

* @var stdClass

*/

private $config;

/**

* 一个二维数组,键是配置文件的section

* 值是一个数组或回调函数

* 如果是数组则计算hostname是否在数组中决定是否使用该section

* 如果是回调函数通过返回值true或false来确定是否使用该section

*

* @var array

*/

private $map = array ();

/**

* section会被解析,:表示继承

* 配置项中的'.'用来区分层级关系

* section中的'.'不会被解析,配置中的数组不受影响。

*

* @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;

}

/**

* 总是返回配置对象

*

* @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默认是浅克隆,函数实现深克隆

*

* @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;

}

/**

* 递归的合并两个对象

*

* @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;

}

}

}

}

简单使用:

?

1

2

3

4

5

6

7
$_ENV ['config'] = new Config ( file_get_contents ( __DIR__ . '/config.ini' ), array (

'development' => array (

'localhost.localdomain',

'localhost'

),

'production' => array ()

) );

配置文件示例:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19
[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

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 一个非常完美的读写ini格式的PHP配置类分享 https://www.kuaiidc.com/102488.html

相关文章

发表评论
暂无评论