0

0

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

php中文网

php中文网

发布时间:2016-05-31 13:17:04

|

1174人浏览过

|

来源于php中文网

原创

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

/**
 * 解析.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;
  }
 }
 }
}

简单使用:

$_ENV ['config'] = new Config ( file_get_contents ( __DIR__ . '/config.ini' ), array (
 'development' => array (
  'localhost.localdomain',
  'localhost'
 ),
 'production' => array ()
) );

配置文件示例:

Cogniflow
Cogniflow

Cogniflow是一个无代码AISaas解决方案,允许用户创建和部署AI模型,

下载

[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

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

智谱清言 - 免费全能的AI助手
智谱清言 - 免费全能的AI助手

智谱清言 - 免费全能的AI助手

相关专题

更多
batoto漫画官网入口与网页版访问指南
batoto漫画官网入口与网页版访问指南

本专题系统整理batoto漫画官方网站最新可用入口,涵盖最新官网地址、网页版登录页面及防走失访问方式说明,帮助用户快速找到batoto漫画官方平台,稳定在线阅读各类漫画内容。

58

2026.02.25

Steam官网正版入口与注册登录指南_新手快速进入游戏平台方法
Steam官网正版入口与注册登录指南_新手快速进入游戏平台方法

本专题系统整理Steam官网最新可用入口,涵盖网页版登录地址、新用户注册流程、账号登录方法及官方游戏商店访问说明,帮助新手玩家快速进入Steam平台,完成注册登录并管理个人游戏库。

6

2026.02.25

TypeScript全栈项目架构与接口规范设计
TypeScript全栈项目架构与接口规范设计

本专题面向全栈开发者,系统讲解基于 TypeScript 构建前后端统一技术栈的工程化实践。内容涵盖项目分层设计、接口协议规范、类型共享机制、错误码体系设计、接口自动化生成与文档维护方案。通过完整项目示例,帮助开发者构建结构清晰、类型安全、易维护的现代全栈应用架构。

7

2026.02.25

Python数据处理流水线与ETL工程实战
Python数据处理流水线与ETL工程实战

本专题聚焦 Python 在数据工程场景下的实际应用,系统讲解 ETL 流程设计、数据抽取与清洗、批处理与增量处理方案,以及数据质量校验与异常处理机制。通过构建完整的数据处理流水线案例,帮助开发者掌握数据工程中的性能优化思路与工程化规范,为后续数据分析与机器学习提供稳定可靠的数据基础。

0

2026.02.25

Java领域驱动设计(DDD)与复杂业务建模实战
Java领域驱动设计(DDD)与复杂业务建模实战

本专题围绕 Java 在复杂业务系统中的建模与架构设计展开,深入讲解领域驱动设计(DDD)的核心思想与落地实践。内容涵盖领域划分、聚合根设计、限界上下文、领域事件、贫血模型与充血模型对比,并结合实际业务案例,讲解如何在 Spring 体系中实现可演进的领域模型架构,帮助开发者应对复杂业务带来的系统演化挑战。

0

2026.02.25

Golang 生态工具与框架:扩展开发能力
Golang 生态工具与框架:扩展开发能力

《Golang 生态工具与框架》系统梳理 Go 语言在实际工程中的主流工具链与框架选型思路,涵盖 Web 框架、RPC 通信、依赖管理、测试工具、代码生成与项目结构设计等内容。通过真实项目场景解析不同工具的适用边界与组合方式,帮助开发者构建高效、可维护的 Go 工程体系,并提升团队协作与交付效率。

18

2026.02.24

Golang 性能优化专题:提升应用效率
Golang 性能优化专题:提升应用效率

《Golang 性能优化专题》聚焦 Go 应用在高并发与大规模服务中的性能问题,从 profiling、内存分配、Goroutine 调度、GC 机制到 I/O 与锁竞争逐层分析。结合真实案例讲解定位瓶颈的方法与优化策略,帮助开发者建立系统化性能调优思维,在保证代码可维护性的同时显著提升服务吞吐与稳定性。

9

2026.02.24

Golang 面试题精选:高频问题与解答
Golang 面试题精选:高频问题与解答

Golang 面试题精选》系统整理企业常见 Go 技术面试问题,覆盖语言基础、并发模型、内存与调度机制、网络编程、工程实践与性能优化等核心知识点。每道题不仅给出答案,还拆解背后的设计原理与考察思路,帮助读者建立完整知识结构,在面试与实际开发中都能更从容应对复杂问题。

5

2026.02.24

Golang 运行与部署实战:从本地到云端
Golang 运行与部署实战:从本地到云端

《Golang 运行与部署实战》围绕 Go 应用从开发完成到稳定上线的完整流程展开,系统讲解编译构建、环境配置、日志与配置管理、容器化部署以及常见运维问题处理。结合真实项目场景,拆解自动化构建与持续部署思路,帮助开发者建立可靠的发布流程,提升服务稳定性与可维护性。

5

2026.02.24

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Django 教程
Django 教程

共28课时 | 4.5万人学习

NumPy 教程
NumPy 教程

共44课时 | 3.5万人学习

XML教程
XML教程

共142课时 | 7.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号