今回はCakePHPで利用できるKeyValueBehaviorについて、実際に使ってみたのでご紹介。
Key-Value Store
先ずはKey-Value Storeについて。
データの保存・管理手法の一つで、任意の保存したいデータ(値:value)に対し、対応する一意の標識(key)を設定し、これらをペアで保存する方式。■ KVSとは 〔 Key-Valueストア 〕 〔 キーバリューストア 〕 - 意味/解説/説明/定義 : IT用語辞典
DB内の1レコードのデータが key = "hoge"、value = "fuga" でできてるものです。
CakePHPには、この仕組みを簡単に取り入れることができるツールがあります。
それが KeyValueBehavior です。
導入
以下で配布されてます。
■ dereuromark/cakephp-tools
この中の以下。
■ cakephp-tools/KeyValueBehavior.php at master · dereuromark/cakephp-tools
ファイルは利用したいプロジェクト内で同じように配置します。
/app/Model/Behavior/KeyValueBehavior.php
DBのテーブルを準備
以下のように保存先のテーブルを作成します。
foreign_id でグルーピングしてひとまとまりのデータとして取扱うカタチです。
CREATE TABLE `sample_tables` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`foreign_id` int(11) DEFAULT NULL,
`key` varchar(255) DEFAULT NULL,
`value` text,
`model` varchar(255) DEFAULT NULL,
`modified` datetime DEFAULT NULL,
`created` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
);
モデルに設定
KeyValue形式で扱いたいモデルで以下の指定を行います。
public $actsAs = array(
'KeyValue',
);
これで準備完了です。
コントローラでの処理
保存時の処理を簡単に書いてみます。
public function edit($foreignId = null) {
if (empty($this->request->data)) {
$this->request->data = $this->{$this->modelClass}->getSection($foreignId);
} else {
if (!$this->{$this->modelClass}->saveSection($foreignId, $this->request->data)) {
$this->Session->setFlash('エラー');
}
$this->redirect(array('action' => 'index'));
}
}
getSection
KeyValue形式で保存されているデータはこのメソッドで取得できます。
$foreignIdでグルーピングされたデータを取得できます。
元のソースは以下のようになってます。
public function getSection(Model $Model, $foreignKey, $section = null, $key = null)
- $foreignKey:グルーピングするIDを指定
- $section:モデル名を指定。指定するとモデル名のキーを含まない配列が取得できる
- $key:指定したキーのデータのみ取得できる
saveSection
KeyValue形式でデータを保存する際はこのメソッドを利用します。
元のソースは以下のようになってます。
public function saveSection(Model $Model, $foreignKey, $data, $section = null, $validate = true)
- $foreignKey:保存時のIDを指定
- $data:保存するデータを指定
- $section:保存時のモデル名を指定
- $validate:バリデーションを実施を指定
key に保存されるデータの形式は以下のようになります。
→ ModelName.key
$validate の指定を false にした場合、保存時にバリデーションの処理が行われません。
resetSection
KeyValue形式で保存されているデータを削除する際はこのメソッドを利用します。
元のソースは以下。
public function resetSection(Model $Model, $foreignKey = null, $section = null, $key = null)
- $foreignKey:削除する対象のグループIDを指定
- $section:削除対象とするモデル名を指定
- $key:指定したキーのデータのみ削除
$sectionと$keyの両方の指定がないときは、テーブルを Truncate します。
バリデーションの指定
KeyValueBehaviorを利用している際にも、バリデーションを利用することができます。
通常、Cakeではモデルのvalidateプロパティに指定します。
このビヘイビアを利用する際は、モデル内に $keyValueValidate プロパティを作り、バリデーション・ルールを指定するカタチになります。
ルールの記述方法に変わりはありません。
■ データバリデーション -- CakePHP Cookbook 2.x ドキュメント
初期値の指定
KeyValueBehavior利用時には、初期値の指定も可能です。
初期値を指定しておきたい場合は、モデル内にkeyValueDefaultsプロパティを設定し、当て込みたいフィールドと値を記述します。
public $keyValueDefaults = array(
'ModelName' => array(
'field' => value,
),
);
ビヘイビアの設定
モデルにビヘイビアを設定する際には、以下の設定を引き渡すことができます。
- 'foreignKeyField' => 'foreign_id',・・・グループIDのフィールド名を指定
- 'keyField' => 'key',・・・保存キーのカラム名を指定
- 'valueField' => 'value',・・・保存値のカラム名を指定
- 'defaults' => null,・・・フォーム初期値を指定
- 'validate' => null,・・・バリデーションルールを指定
- 'defaultOnEmpty' => false,・・・保存データを何も送らない場合は、指定グループIDのデータを削除するかどうか、を指定
- 'deleteIfDefault' => false,・・・保存データがフォーム初期値と同一の場合は、そのデータを削除するかどうか、を指定
その他
1つのデータを配列で処理する場合には、モデルの beforeSave でシリアライズ(or json_encode)し、文字列として保存するようにします。
取り出す際には、モデルの afterFind でアンシリアライズ(or json_decode)し、復元して利用すると良いです。
導入するメリット
KeyValueビヘイビアを利用すると、Key-Value ストアの仕組みをコアに手を入れず手軽に導入することができます。
バリデーションを作成する際にも、通常のルール指定と同様で作成することができます。
追加時の初期値指定も簡単に行うことができるため、かなり便利なビヘイビアとなってます。
あとがき
KeyValue形式で作っておくと、あとから項目追加となった場合にもテーブル構造を変更する必要がありません。
マスタデータとしても、ログデータとしても利用できます丶(・ω・)ノ