【cakephp2】hasOneをbindmodelでつないで保存しようとしても途中でbindが切れる

hasOneをbindModelで繋いでsaveAssociateするとき、
bindModelの第二引数にfalseを設定して永続化しないと途中でbindが切れる。

原因

繋がっている各テーブルに対しUPDATEその他諸々が走るため。
一つの$this->Model->saveAssociate()でも実際のクエリに対してbindModelのフォーカスは決まるっぽい

hasOneのアソシエーションを保存するとき実際に走るクエリ

AuthorTable ->hasOne-> AccountTableの時の例

7つもクエリが走っている

  1. トランザクション開始
  2. AuthorTableの存在チェック(validate用)
  3. AuthorTableの存在チェック(save用)
  4. AuthorTableの更新
  5. AccountTableの存在チェック(validate用)
  6. AccountTableの存在チェック(save用)
  7. AccountTableのの更新
  8. トランザクションコミット
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
[0] => Array
(
[query] => BEGIN
[params] => Array
(
)

[affected] => 1
[numRows] => 1
[took] => 0
)

[1] => Array
(
[query] => SELECT COUNT(*) AS `count` FROM `database`.`author` AS `Author` WHERE `Author`.`id` = 1
[params] => Array
(
)

[affected] => 1
[numRows] => 1
[took] => 0
)

[2] => Array
(
[query] => SELECT COUNT(*) AS `count` FROM `database`.`author` AS `Author` WHERE `Author`.`id` = 1
[params] => Array
(
)

[affected] => 1
[numRows] => 1
[took] => 0
)

[3] => Array
(
[query] => UPDATE `database`.`author` SET `id` = 1, `login_id` = 'hoge', `name` = 'John ', `tel` = '000-0000-0000', `created` = '2016-01-28 22:23:33', `modified` = '2019-07-09 19:09:08', WHERE `database`.`author`.`id` = '1'
[params] => Array
(
)

[affected] => 1
[numRows] => 1
[took] => 7
)

[4] => Array
(
[query] => SELECT COUNT(*) AS `count` FROM `database`.`accounts` AS `Account` WHERE `Account`.`id` = 1
[params] => Array
(
)

[affected] => 1
[numRows] => 1
[took] => 0
)

[5] => Array
(
[query] => SELECT COUNT(*) AS `count` FROM `database`.`accounts` AS `Account` WHERE `Account`.`id` = 1
[params] => Array
(
)

[affected] => 1
[numRows] => 1
[took] => 0
)

[6] => Array
(
[query] => UPDATE `database`.`accounts` SET `auther_id` = 1, `id` = 1, `modified` = '2019-07-09 19:49:27' WHERE `database`.`accounts`.`id` = '1'
[params] => Array
(
)

[affected] => 1
[numRows] => 1
[took] => 0
)

[7] => Array
(
[query] => COMMIT
[params] => Array
(
)

[affected] => 1
[numRows] => 1
[took] => 0
)

)

cakeの仕様だが、validateとsaveで二回も存在チェックする必要はあるだろうか。いや、ない。

補足 複数のSELECT COUNT(*)について

cakephp2ではsaveでもvalidateでも、hasAnyの時でさえも存在チェックとしてSELECT COUNT()を使う。
$Model->find()の時ですら件数取得としてSELECT COUNT(
)を使う。
すでにvalidatesメソッドでSELECT COUNT()していようが、saveの時にまたSELECT COUNT()を使う。
詳しくはVendor/cakephp/cakephp/lib/Cake/Model.phpVendor/cakephp/cakephp/lib/Cake/ModelBehavior.phpに。