CakePHP 2.x でバリデート前にまとめてデータを加工する
最近業務で CakePHP を使い始めたので備忘録的な。
FuelPHP などに慣れていると、バリデートのルールと一緒にフィルタ処理したい衝動に駆られる。
こういった機構は CodeIgniter や Phalcon など実装されてたと思う(Phalcon はうろ覚え)
CakePHP においてバリデート時にフィルタを掛けるなら、beforeValidate というコールバックメソッドを用意してあげれば良いみたい。
汎用的に使おうと思ったらこんな感じ?
テスト環境:
CakePHP 2.6.2
PHP 5.6.6
▼ AppModel.php
<?php /** * Application model for Cake. * * This file is application-wide model file. You can put all * application-wide model-related methods here. * * @link http://cakephp.org CakePHP(tm) Project * @package app.Model * @since CakePHP(tm) v 0.2.9 */ App::uses('Model', 'Model'); /** * Application model for Cake. * * Add your application-wide methods in the class below, your models * will inherit them. * * @package app.Model */ class AppModel extends Model { /** * バリデート前に実行するフィルタ一覧 * * @var array */ public $filters = []; /** * バリデート前に実行するイベント * * @param array $options オプション * @return bool */ public function beforeValidate($options = []) { $result = parent::beforeValidate($options); if ($result && $this->filters) { array_walk($this->data[$this->name], function (&$value, $key) { if (!isset($this->filters[$key])) { return; } foreach ($this->filters[$key] as $filter) { if (is_string($filter)) { $value = call_user_func($filter, $value); } elseif (is_array($filter)) { $callback = array_shift($filter); array_unshift($filter, $value); $value = call_user_func_array($callback, $filter); } } }); } return $result; } }
あとは継承先で、$filters プロパティを用意して指定してあげるだけ。
<?php class Hoge extends AppModel { public $filters = [ 'title' => ['trim', [['self', 'upper']]], ]; /** * 小文字を大文字に変換します。 * * @param string $str 対象の文字列 * @return string 変換後の文字列 */ public static function upper($str) { return strtoupper($str); } }
この場合、title というデータにビルトイン関数 trim と、Hoge#upper を実行することになる。