cakePHP には Validation という便利な機能が標準で搭載されています。


これは例えば、
 users テーブルの name フィールドの値は2文字以上30文字以内
というルールをアプリケーションのレベルで付与する、というものです。「アプリケーションのレベルで」付与するので、例えば入力の際のエラーメッセージも併せて定義することができます。

具体的にはこんな感じでモデルにルールを記述することになります。上記例では users テーブルを対象にしているので、モデルは Model/User.php ファイルとなり、その中に以下の様な Validation ルールを加えます:
<?php
App:uses('AppModel', 'Model' );
class User extends AppModel{
  :
  :
  
  public $validate = array(
    'name' => array(
      'between' => array(
        'rule' => array('between',2,30),
        'message' => '名前は2文字以上30文字以内で入力してください。'
      )
    )
  );
}
?%gt;

これで User モデルに Validation ルールが適用され、この条件に合わないデータ配列で save() メソッドを実行しても保存できなくなります。その際に定義されているエラーメッセージを取得することもできるので、それを画面に表示して再入力を促すこともできます。


これはこれで便利なのですが、アプリケーションを運用しているとこのルールを変えたくなることがあります。例えば name フィールドの値を5文字以上50文字以内に変更したい、というケースを考えます。

モデルのルールとしては上記の $validation 変数の該当部分を array('between',2,30) から array('between',5,50) に変え、エラーメッセージも新しいものに変更するだけで済みます。しかしこれだけでは問題が起こることもあります。


例えば元の Validation ルール運用時にユーザーがデータを作り、その後新しい Validation ルールに変えたとします。そしてユーザーや管理者が、現在の users データのあるレコードの、name フィールドではない別のフィールドの値を変えたいと思っている、という状況を考えてみてください:

(例) 管理者が id = 10 のユーザーの admin_flag 列の値を 0 から 1 に変えたい、と思っている。。。

idnameadmin_flag
10ABC0


ロジックそのものは単純で、こんな感じになります:
    :
//. id = 10 の User を検索 $user = $this->User->find('first', array('conditions'=>array('id'=>'10'));
//. admin_flag の値を 1 に変更 $user['User']['admin_flag'] = 1;
//. 更新して保存 $this->User->save($user['User']);
:

しかしこのロジックには問題があり、実行しても admin_flag の値は更新されません。 その理由は今は新しい Validation ルールで運用されているため、name 値は5文字以上になっている必要がある、というルールが適用されるためです。現在の "ABC" という name 値は以前のルールでは問題なく作れていても今のルールでは認められません。そのため save に失敗してしまいます。

その一方で、これは管理・運用上の処置であるため、ユーザーの意志とは関係なく管理者が行う必要のある作業であるケースもありえます。name 値が現行の Validation ルールにはそぐわないものであったとしても、この変更を保存できるようにしたいのですが、何か方法はないでしょうか?


で、その答がこのブログエントリのテーマでもある「Validation ルールを一時的に無効にする」です。実はすごく簡単で、最後の save メソッド実行時に第二パラメータを指定します:
    :
//. id = 10 の User を検索 $user = $this->User->find('first', array('conditions'=>array('id'=>'10'));
//. admin_flag の値を 1 に変更 $user['User']['admin_flag'] = 1;
//. 更新して保存 $this->User->save($user['User'], false);
:

これで Validation ルールを一時的に無効にした上で save メソッドを実行することができます。