一个非常完美的读写ini格式的PHP配置类分享
这篇文章主要介绍了一个非常完美的读写ini格式的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 $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 () ) );
配置文件示例:
[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

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

如何使用PHP實現資料快取和讀寫功能快取是提高系統效能的重要方式,透過快取可以將頻繁使用的資料儲存在記憶體中,以提高資料的讀取速度。在PHP中,我們可以使用各種方法來實現資料快取和讀寫功能。本文將介紹兩種常用的方法:使用檔案快取和使用記憶體快取。一、使用檔案快取檔案快取是將資料儲存在檔案中,以便後續讀取。下面是一個使用檔案快取實現資料讀寫的範例程式碼:

概念fio,又稱為FlexibleIOTester,是JensAxboe編寫的應用程式。 Jens是LinuxKernel中blockIOsubsystem的維護者。 FIO是一種用於測試網路檔案系統和磁碟效能的工具,常用於驗證機型和比較檔案系統效能。它能自動將fio指令傳送到群集機器列表,並收集小檔案的IOPS和大檔案的吞吐量資料。 rw=[mode]rwmixwrite=30在混合讀寫的模式下,寫佔30%moderead順序讀write順序寫readwrite順序混合讀寫randwrite隨機寫r

檔案系統APIJava檔案操作的內部原理與作業系統的檔案系統api密切相關。在Java中,檔案操作是由java.NIO套件中的java.nio.file模組提供的。本模組提供了檔案系統API的封裝,使Java開發者能夠在不同的作業系統上使用統一的API進行檔案操作。檔案物件當Java程式需要存取檔案時,它首先需要建立一個java.nio.file.Path物件。 Path物件代表了檔案系統中的一個路徑,可以是絕對路徑也可以是相對路徑。一旦建立了Path對象,就可以使用它來取得文件的各種屬性,例如名稱

解密Java中處理DBF檔案的讀取和寫入方法DBF(dBASEFile)是一種常見的資料庫檔案格式,通常用於儲存表格資料。在Java程式中,處理DBF檔案的讀取和寫入是一個比較常見的需求。本文將介紹如何使用Java解密此過程,並提供具體的程式碼範例。一、讀取DBF檔案在Java中,讀取DBF檔案通常需要藉助第三方函式庫,例如使用dbfread函式庫。首先需要在項目

在Java開發中,處理並發讀寫資料一致性問題是非常重要的。隨著多執行緒和分散式系統的流行,同時讀寫資料的情況越來越普遍,如果不謹慎處理,可能會導致資料的不一致性。本文將介紹幾種常見的處理並發讀寫資料一致性問題的方法。一、使用鎖定機制最常用的處理並發讀寫資料一致性問題的方法之一就是使用鎖定機制(如synchronized關鍵字或ReentrantLock類別)。通

Excel檔案作為一種常用的表格檔案格式,經常在開發過程中被使用。 PHP作為常用的程式語言,也支援Excel檔案的讀寫操作。在本文中,我們將介紹如何使用PHP實作Excel檔案的讀寫操作。安裝PHPExcel庫PHPExcel是一個開源的PHP函式庫,可以方便地對Excel檔案進行讀寫操作。它可以透過Composer進行安裝,也可以直接從GitHub下載

PHP檔案讀寫教學:詳細介紹讀取和寫入的基本方法和流程引言:在開發Web應用程式時,檔案的讀取和寫入操作是非常基礎且常見的操作。 PHP提供了一系列的方法和函數來實作檔案讀寫操作,而且非常簡單易用。本教學將詳細介紹PHP中檔案的讀取和寫入的基本方法和流程,並給出程式碼範例。一、文件的讀取開啟檔案在開始讀取檔案前,首先需要開啟檔案。可以透過fopen()函數來打開

隨著網路的普及,Web應用程式已經成為了商業行銷和社交交流的重要工具。 Web應用程式的快速讀寫是Web應用程式設計中的一個基本問題。 Golang作為一種高效且簡潔的程式語言,可以幫助程式設計師實現快速讀寫的需求。在本文中,我們將學習如何使用Golang實作網頁應用程式的快速讀寫。一、建立資料庫連線在使用Golang實作網頁應用程式的快速讀寫前,我們要建立
