-
Notifications
You must be signed in to change notification settings - Fork 0
/
AssociationCollection.php
276 lines (235 loc) · 7.42 KB
/
AssociationCollection.php
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
<?php
namespace TRW\ActiveRecord;
use TRW\ActiveRecord\Association\BelongsTo;
use TRW\ActiveRecord\Association\HasMany;
use TRW\ActiveRecord\Association\HasOne;
use TRW\ActiveRecord\Association\BelongsToMany;
/**
* このクラスはレコードクラスの関連情報の保持と関連するレコードオブジェクトの保存を行う.
*
* このクラスは\TRW\ActiveRecord\BaseRecordが<br>
* 内部で利用するためだけのクラスのため<br>
* 一般開発者はこのクラスを使用してはならない
*
* @access private
*/
class AssociationCollection {
/**
* レコードクラス毎のアソシエーション情報を保持している.
*
*その構造は以下のようになっている<br>
* $assoiations = <br>
* [
* 'User' => [ <br>
* 'type' => [ <br>
* new HasOne('App\Model\User', 'App\Model\Profile'),<br>
* new HasMany('App\Model\User', 'App\Model\Comment') <br>
* ]<br>
* ],<br>
* 'Profile' => [<br>
* 'type' => [<br>
* new BelongsTo('App\Model\Profile', 'App\Model\User')<br>
* ]<br>
* ],<br>
* 'Comment' => [ <br>
* 'type' => [ <br>
* new BelongsTo('App\Model\Comment', 'App\Model\User')<br>
* ]<br>
* ]<br>
* ]<br>
*
*
* @var array レコードクラス毎のアソシエーション情報
*/
private static $associations;
private function __construct(){}
/**
* 指定したレコードクラスののアソシエーション情報をクリアする.
*
* @param string $name レコードクラス名
* @return void
*/
public static function removeAssotiation($name){
self::$associations[$name] = null;
}
/**
* アソシエーション情報を全てクリアする
*
* @return void
*/
public static function clearAll(){
self::$associations = [];
}
/**
* BelongsToオブジェクトを生成する.
*
* @param string $own 関連を定義したクラス名
* @param string $target 関連で指定されたクラ名ス
* @return \TRW\ActiveRecord\Association\BelongsTo
*/
private static function BelongsTo($own, $target, $option){
return new BelongsTo($own, $target, $option);
}
/**
* HasOneオブジェクトを生成する.
*
* @param string $own 関連を定義したクラス名
* @param string $target 関連で指定されたクラ名ス
* @return \TRW\ActiveRecord\Association\HasOne
*/
private static function HasOne($own, $target, $option){
return new HasOne($own, $target, $option);
}
/**
* HasManyオブジェクトを生成する.
*
* @param string $own 関連を定義したクラス名
* @param string $target 関連で指定されたクラ名ス
* @return \TRW\ActiveRecord\Association\HasMany
*/
private static function HasMany($own, $target, $option){
return new HasMany($own, $target, $option);
}
/**
* BelongsToManyオブジェクトを生成する.
*
* @param string $own 関連を定義したクラス名
* @param string $target 関連で指定されたクラ名ス
* @return \TRW\ActiveRecord\Association\BelongsToMany
*/
private static function BelongsToMany($own, $target, $option){
return new BelongsToMany($own, $target, $option);
}
/**
* レコードクラスのアソシエーション情報から適切なアソシエーションクラスを生成する.
*
* 名前空間が動的インスタンスの生成の影響を受けないため、<br>
* メソッド内で直接生成した
*
* @param string $own アソシエーションを定義したクラス
* @param array $associationMap アソシエーション情報
* @return array アソシエーション情報
*/
public static function associations($own = null, $associationMap = null){
if($associationMap === null || $own === null){
return self::$associations;
}
if(!empty(self::$associations[$own])){
return self::$associations[$own];
}
foreach($associationMap as $type => $targets){
foreach($targets as $target => $option){
self::$associations[$own][$type][] = self::$type($own, $target, $option);
}
}
return self::$associations[$own];
}
/**
* 関連するレコードオブジェクトを取得する.
*
* @param \TRW\ActiveRecord\BaseRecord $record レコードオブジェクト
* @param array $associationMap 関連レコード情報
* @throws \Exception @param $record @param $associationMapがnullの時
*/
public static function attach($record, $associationMap){
if($record === null){
throw new Exception('arguments error record is null');
}
if($associationMap === null){
return;
}
$recordClass = get_class($record);
$associations = self::associations($recordClass, $associationMap);
foreach($associations as $sourceTable => $assoc){
foreach($assoc as $type){
$target = $type->target();
$record->$target = $type->find($record);
}
}
}
/**
* 対象のレコードクラスの関連レコードクラス名を取得する.
*
* @param string $tableName レコードクラス名
* @return array 関連するレコードクラス名リスト
*/
public static function hasAssociatedTarget($tableName){
$associations = self::get($tableName);
if(empty($associations)){
return [];
}
$result = [];
foreach($associations as $table => $assoc){
foreach($assoc as $type){
$result[] = $type->target();
}
}
return $result;
}
/**
* レコードクラスの関連情報を取得する.
*
* @param 関連を取得したいレコードクラス名
* @return boolean|array 関連データがあればarray なければfalse
*/
public static function get($tableName){
if(empty(self::$associations[$tableName])){
return false;
}
return self::$associations[$tableName];
}
/**
* レコードオブジェクト保持している関連レコードオブジェクトを保存する.
*
* @access private
* @param \TRW\ActiveRecord\BaseRecord $record レコードオブジェクト
* $param array $associations レコードオブジェクトのアソシエーション情報
* @param boolean $owningSide 自身で保持しているか保持されているか
* @return boolean 保存に成功すればtrue 失敗すればfalse
*/
private static function saveAssociations($record, $associations, $owningSide){
foreach($associations as $assocs){
foreach($assocs as $type){
if($type->isOwningSide($record) !== $owningSide){
continue;
}
if(!$type->save($record)){
return false;
}
}
}
return true;
}
/**
* レコードオブジェクトが属している親を保存する.
*
* ここでいう親とは継承関係の親クラスを指すものではなく<br>
* アソシエーション上の親の事
*
* @param \TRW/ActiveRecord\BaseRecord $record レコードオブジェクト
* @return boolean レコードの保存に成功すれば true 失敗すればfalse
*/
public static function saveParents($record){
if(empty(self::$associations[get_class($record)])){
return true;
}
$associations = self::get(get_class($record));
return self::saveAssociations($record, $associations,false);
}
/**
* レコードオブジェクトが保持している子を保存する.
*
* ここでいう子とは継承関係の子クラスを指すものではなく<br>
* アソシエーション上の子の事
*
* @param \TRW/ActiveRecord\BaseRecord $record レコードオブジェクト
* @return boolean レコードの保存に成功すれば true 失敗すればfalse
*/
public static function saveChilds($record){
if(empty(self::$associations[get_class($record)])){
return true;
}
$associations = self::get(get_class($record));
return self::saveAssociations($record, $associations,true);
}
}