隨着PHP7的發佈, 新增了不少持久化類型的支持好比IS_IMMUTABLE_ARRAY, 因而我就在PHP7下從新開發了Yaconf, 開源出來, 方便你們使用.
簡介php
首先說說, 這個是幹啥的.mysql
我見過不少的項目中, 用PHP文件作配置的, 一個config目錄下可能有十幾個甚至數十個.php配置文件, 裏面都是各類各樣的array, 還有甚者會把一些詞典文件(好比中文/英文對照)也放到配置中去. 這就致使配置文件的解析耗費了很大的性能(誠然, 用了opcache能好點, 可是實際上仍是有執行的過程).sql
除了PHP的, 還有用json的, yaml的, 一個共同的特色就是這些配置的可讀性比較差. 另外, 他們也都要runtime解析.json
config目錄每每和代碼在一塊兒, 首先會有安全隱患(配置中每每有敏感信息), 其次若是配置和代碼屬於一個項目, 這就會致使配置的修改也要走代碼上線的流程.數組
一些資源配置文件, 好比mysql/memcache的配置信息, 這些內容原本是應該對開發透明的, 運維直接負責便可. 可是放到了代碼中就會致使, 運維若是要發起一些變動, 也要開發配合修改配置文件上線.緩存
因此, Yaconf就是爲了解決這些問題而生的一個工具.安全
它使用單獨的一個配置目錄(在yaconf.directory指定), 不和代碼在一塊兒.php7
它在PHP啓動的時候, 處理全部的要處理的配置, 而後這些配置就會常駐內存, 隨着PHP的生命週期存亡. 避免了每次請求的時候解析配置文件.框架
全部的配置內容都是immutable的, 這就能夠藉助於Fork的COW, 下降內存佔用, 而且在訪問配置的時候, 幾乎不須要任何的內存Copy, 也不會有無謂的引用計數增減運維
最重要的, 配置目錄和代碼分離之後, 能夠藉助一個配置管理後臺, 來實現配置的統一化管理.
它支持(對於非ZTS)配置變動從新加載, 也就是說配置若是有變化(建議更改配置必定使用mv, 不要使用cp), 它會reload, 不須要重啓(檢測的頻率由yaconf.check_delay控制).
它支持豐富的配置類型, 包括字符串, 數組, 分節, 分節繼承, 而且還能夠在配置中直接寫PHP的常量和環境變量等.
最重要的是, 它很簡單.
API
Yaconf 只提供了倆個方法,
mixed Yaconf::get(string $name, mixed $default = NULL) 這個是獲取一個配置, 名字是配置的名字, 通常來講若是你有一個ini文件叫作foo.ini, 那麼$name使用foo的話就會獲取到這個文件內的全部內容, 以數組形式返回. default是當配置不存在的時候返回的默認值. bool Yaconf::has(string $name) 這個是檢測一個配置是否存在.
Yaconf的配置項
yaconf.directory 配置文件目錄, 這個配置不能經過ini_set指定, 由於必須在PHP啓動的時候就肯定好. yaconf.check_delay 多久(秒)檢測一次文件變更, 若是是0就是不檢測, 也就是說若是是0的時候, 文件變動只能經過重啓PHP從新加載
配置的格式
Yaconf採用ini文件做爲配置文件, 這是由於我一直以爲ini是最適合作配置文件的, key-value格式, 清晰可讀.
簡單的配置寫起來以下(如下所有假設ini文件的名字是test):
foo="bar" phpversion=PHP_VERSION env=${HOME}
如上所示, 對於通常的配置咱們都用引號引發來. 而對於沒有引發來的, 會嘗試以PHP的常量作解釋, 也就是說咱們能夠直接在配置裏面寫PHP的常量.
另外你也看到了, 咱們能夠直接在配置中寫環境變量, 好比上面的env:
Yaconf::get("test.env"); //test是配置文件名字 //string(16) "/home/huixinchen"
如上面所示, 你能夠看到, 假設對於foo的值, 你能夠經過以下代碼訪問:
Yaconf::get("test.foo"); //test是配置文件名字
Yaconf也支持數組類型的配置, 寫法以下:
arr[]=1 arr.1=2
如上面所示你能夠直接使用foo[]這種形式來定義數組, 也可使用arr.1, arr.2來指定key定義.
對於數組的第二個值, 你能夠經過以下代碼訪問:
Yaconf::get("test.arr.1"); //test是配置文件名字
或者你能夠經過獲取整個arr數組以後訪問:
$arr = Yaconf::get("test.arr"); //test是配置文件名字 echo $arr[1];
Yaconf也支持map類型的配置, 寫法以下:
map.foo=bar map.bar=foo ;你可使用分號來寫註釋 map2.foo.name=yaconf map2.foo.year=2015
對於map2的foo子map的name值能夠經過以下形式訪問:
Yaconf::get("test.map2.foo.name"); //test是配置文件名字
而且, 配置文件還能夠分節, 和分節繼承:
[parent] parent="base" children="NULL" [children : parent] children="children"
請注意配置的分節繼承的語法 children:(冒號)parent, 這的意思是children節繼承所有base的配置項. 而後你在children節裏面定義的和parent節中同名的配置, 會覆蓋掉parent中定義的內容.
對於chidlren節的children配置的值能夠經過以下形式訪問:
Yaconf::get("test.children.children"); //test是配置文件名字
樣例
首先, 假設咱們的全部的配置文件都放置在/tmp/yaconf中, 那麼咱們就須要在php.ini中增長以下配置:
yaconf.directory=/tmp/yaconf
這樣yaconf在PHP啓動的時候, 就會在這個目錄下找全部的.ini文件, 而後嘗試處理他們. 這裏要注意的是不支持多級目錄, 也就是說, yaconf只會處理yaconf.directory內的.ini文件, 不會處理子目錄裏面的(這主要是爲了簡單考慮, 由於有分節, 你就能夠一個項目定義一個ini文件).
假設/tmp/yaconf下有倆個ini文件, 分別是:
foo.ini
name="yaconf" year=2015 features[]="fast" features.1="light" features.plus="zero-copy" features.constant=PHP_VERSION
bar.ini
[base] parent="yaconf" children="NULL" [children:base] children="set"
而後對於foo的內容:
php7 -r 'var_dump(Yaconf::get("foo"));' /* array(3) { ["name"]=> string(6) "yaconf" ["year"]=> string(4) "2015" ["features"]=> array(4) { [0]=> string(4) "fast" [1]=> string(5) "light" ["plus"]=> string(9) "zero-copy" ["constant"]=> string(9) "7.0.0-dev" } } */
對於bar的內容:
php7 -r 'var_dump(Yaconf::get("bar"));' /* array(2) { ["base"]=> array(2) { ["parent"]=> string(6) "yaconf" ["children"]=> string(4) "NULL" } ["children"]=> array(2) { ["parent"]=> string(6) "yaconf" ["children"]=> string(3) "set" } } */
固然你能夠用 (.)連接語法精確訪問任何一個特定的值.
最後
個人Ya系列擴展今後又多了一個新成員, 算上以前的Yaf(PHP框架), Yar(PHP RPC框架), Yac(PHP單機緩存), 你們就能夠很容易搭建一套高性能的LAMP應用解決方案出來.最後: Yaconf要求PHP7才能用, 而PHP7的alpha1版本今天已經發布了, 歡迎你們測試(關於alpha不alpha, 只要你的項目沒有觸發到有bug的地方, 那麼對你來講就能夠用, 不是麼? )