save(), saveAll()の$fieldList設定

前日、関連モデルがある場合の$fieldListは、[テーブル名].[フィールド名]で設定と記載しましたが、むしろ間違いでした。
$fieldListの設定には、テーブル名を入れてはいけません。

以下、$fieldListチェックの動作検証です。

$fieldListチェックの解析

$fieldListチェックは、以下のsave()内で行われています。

cake/libs/model/model.php 1218行目

foreach ($v as $x => $y) {
	if ($this->hasField($x) && (empty($this->whitelist) || in_array($x, $this->whitelist))) {
		list($fields[], $values[]) = array($x, $y);
	}
}

saveAll()も、内部でsave()を繰り返し実行なので$fieldListチェックは同じ箇所で行われています。


上記、$vは$this->data[Model]。

例えば Characterを保存する際には、こんなデータが入ってきます。

var_dump($v)

array(9) {
 ["public_flag"]=>  string(6) "public"
 ["id"]=>  string(1) "4" 
(中略)
["modified"]=>  string(19) "2010-01-29 10:52:28" }


$xは$vのキーなので、出力するとこうなります。

string(11) "public_flag"
string(2) "id"
(中略)
string(8) "modified" 


一方$this->whitelistは、$fieldListの設定、プラスcreted/modifiedが入っています*1


この条件で

$this->hasField($x)

$x=POSTのkeyと同名のfieldがテーブルに存在して、かつ

(empty($this->whitelist) ||

$fieldListの設定がない場合、あるいは

in_array($x, $this->whitelist))

$xが$this->whiteListに含まれている場合。


・・・3つめのロジックがポイントでした。

in_array("public_flag", array("public_flag", "id", "modified")) は trueですが、
in_array("public_flag", array("Character.public_flag", "Character.id", "modified")) は falseです。


と、言う事で前日の記載は誤りで、むしろ$fieldListの設定にテーブル名は入れてはいけないという結論に達しました。
  動作確認時に誤認したものと思われます・・・・

saveAll()の場合の$fieldList

saveAllの場合、保存するモデルごとにsave()が発行されますが、
 $fieldListは全て同じものを使っています。

なので、モデルAとモデルBを同時にsaveAllする場合は、両方の$fieldListをarray_mergeしてセットします。


ここで、疑問に思うのは
「AとBに同じfield名のカラムがあって、Aは更新OKだけどBは更新したくない」という場合。

・・・・field名が被らないように設計しましょう、と? ^^;

*1:$fieldListを設定しない場合は、created/modifiedも入ってきません