設定ファイルのconcatと設定ファイルの継承と
設定ファイルのconcatについてのメモ。例えばconcatと言っても以下の3つくらいの段階がある。
例えば、以下のようなyamlがあるとする。
person.yaml
definitions: person: properties: name: type: string age: type: integer
skill.yaml
definitions: skill: properties: name: type: string description: type: string
単にファイル単位でconcatするだけ
単にファイル単位でconcatするだけの場合にはcatでつなげる。
$ cat person.yaml skill.yaml > bundle0.yaml
もちろんただ単に繋げられただけ。
definitions: person: properties: name: type: string age: type: integer definitions: skill: properties: name: type: string description: type: string
JSONの構造を意識しながらトップレベルの要素同士をconcat
JSONの構造を意識しながらトップレベルの要素同士をconcatしたければ、dictknifeが使える。
$ dictknife concat person.yaml skill.yaml > bundle1.yaml
definitions部分にまとめられる。
definitions: person: properties: name: type: string age: type: integer skill: properties: name: type: string description: type: string
自由な位置に所定の要素を参照(not concat)
自由な位置に所定の要素を埋め込むことはdictknifeではできない。jsonknifeのderefを使えば出来なくはない。ただし、これの意味あいはjson referenceのderef。
main.yaml
definitions: myperson: $ref: "./person.yaml#/definitions/person" myskill: $ref: "./skill.yaml#/definitions/skill"
$ jsonknife deref --src main.yaml > bundle2.yaml
personではなくmypsersonの位置にperson.yamlのpersonの値を置ける。
definitions: myperson: properties: name: type: string age: type: integer myskill: properties: name: type: string description: type: string
jsonschemaやswaggerなどのschemaファイルだとこれだけでも良いのだけれど。設定ファイルだとまた違った性質の機能が欲しくなる。
自由な位置に所定の要素をconcat
自由な位置に所定の要素をconcatができれば継承は結構手軽に作れる。例えばこのstack overflowの質問。
PHPにはJSONを拡張した継承付きで読み込むための機能が存在するらしい(らしい)。これと似たようなことをしようとすると、任意の位置に値を挿入しつつrefを使ったように単なる参照だけでは済まない形になる。任意の位置にconcatされて欲しい。
zenmaiでこれをできるようにした(zenmaiはdictknifeに依存している)。
上の質問のconfigをyamlに変換してちょっとだけ形を変えてみたものが以下のようなもの(_extends
のかわりに $inherit
になっている)。
production: phpSettings: display_startup_errors: false display_errors: false includePaths: library: APPLICATION_PATH/../library bootstrap: path: APPLICATION_PATH/Bootstrap.php class: Bootstrap appnamespace: Application resources: frontController: controllerDirectory: APPLICATION_PATH/controllers moduleDirectory: APPLICATION_PATH/modules params: displayExceptions: false modules: [] db: adapter: pdo_sqlite params: dbname: APPLICATION_PATH/../data/db/application.db layout: layoutPath: APPLICATION_PATH/layouts/scripts/ staging: $inherit: "#/production" testing: $inherit: "#/staging" phpSettings: display_startup_errors: true display_errors: true development: $inherit: "#/staging" resources: frontController: params: displayExceptions: true
例えば、develpmentから見ると staging -> production
という継承が行われて欲しい。zenmaiで変換した結果をとりだす(ついでに --select
オプションを追加した。変換結果の一部分だけが欲しいので)。
$ zenmai config.yaml --select '#/development' > dev.yaml
dev.yaml
phpSettings: display_startup_errors: false display_errors: false includePaths: library: APPLICATION_PATH/../library bootstrap: path: APPLICATION_PATH/Bootstrap.php class: Bootstrap appnamespace: Application resources: frontController: controllerDirectory: APPLICATION_PATH/controllers moduleDirectory: APPLICATION_PATH/modules params: displayExceptions: true modules: [] db: adapter: pdo_sqlite params: dbname: APPLICATION_PATH/../data/db/application.db layout: layoutPath: APPLICATION_PATH/layouts/scripts/
そんなわけでちょこっと手を加えれば結構柔軟なconfig loaderが作れる気がする。