我寫了一個類似於可容納的函數來執行深層查詢。
數據得到的返回格式與您期望從可容納的相同。
如果您需要將其他搜索條件添加到查詢的子級別,它可能很有用。
簡而言之,該功能允許您按照自己的想法深入鑽取,而不會返回所有多餘的垃圾,但可以讓您更多地控制調用之間發生的情況。
可封閉很棒,但不會調用可能需要調用的行爲和其他函數。
例如:我需要在每次調用後對返回的數據運行一個acl過濾器。無法找到一種方式來做到這一點與可容納。
現在很容易在該腳本的開頭和結尾添加額外的函數調用作爲前後調用操作。
只需將其插入您的AppModel並觀看魔術發生。
下面是一個電話是什麼樣子的一個例子:
$options = ['conditions'=>['User.id'=>9]];
$options['drill'] => ['Relation1', 'Relation2'=>['drill'=>['Subrelation1', 'Subrelation2'=>['drill'=>['ThirdLevelRelation']]]]];
$this->request('find', $options);
這裏是如何添加選項子關係。
$options['drill'] => ['Relation1', 'Relation2'=>['fields'=>['field_a','field_b'], 'conditions'=>['alias'=>'test'], 'drill'=>[....] ]];
這裏所說:
public function request($method='first', $options=array()){
$result = $this->find($method, $options);
if(isset($options['drill'])){
$bits = $bitOptions = $subDrils = $subBits = [];
if(is_array($options['drill'])){
foreach($options['drill'] as $key => $val){
if(is_array($val)){
$bits[]=$key;
$bitOptions[$key] = $val;
if(isset($val['drill'])){
if(is_array($val['drill'])){
foreach($val['drill'] as $sKey => $sVal){
$subBits[$key][] = is_array($sVal)?$sKey:$sVal;
}
} else {
$subBits[$key][] = $val['drill'];
}
}
} else {
$bits[] = $val;
}
}
} else {
$bits[] = $options['drill'];
}
foreach($bits as $bit){
if(isset($gems)){unset($gems);$gems=[];}
if(isset($result[$bit])){
$gems[] =& $result[$bit];
} else {
foreach($result as $k => $v){
if(isset($result[$k][$bit])){
$gems[] =& $result[$k][$bit];
}
}
}
foreach($gems as $key => $gem){
if(!empty($gem)){
$m = $this->$bit;
if(is_object($m)){
foreach(['hasOne','belongsTo','hasMany','hasAndBelongsToMany'] as $relation){
foreach(array_keys($m->$relation) as $alias){
if(isset($subBits[$bit])){
if(!in_array($alias, $subBits[$bit])){
$m->unBindModel([$relation=>[$alias]]);
}
}
}
}
if(!empty($subBits[$bit])){
$opts = isset($bitOptions[$bit])?$bitOptions[$bit]:[];
if(isset($gem[$m->primaryKey])){
if(!isset($opts['conditions'])){
$opts['conditions'] = [$m->alias.'.'.$m->primaryKey=>$gem[$m->primaryKey]];
} else {
$opts['conditions'] = Hash::merge($opts['conditions'], [$m->alias.'.'.$m->primaryKey=>$gem[$m->primaryKey]]);
}
if($r = $m->request('first', $opts)){
unset($r[$m->alias]);
$gems[$key] = Hash::merge($gems[$key], $r);
}
} else {
reset($gem);
$first_key = key($gem);
$first = $gem[$first_key];
if(isset($first[$m->primaryKey])){
foreach($gem as $gemKey => $gemVal){
if(!isset($opts['conditions'])){
$opts['conditions'] = [$m->alias.'.'.$m->primaryKey=>$gemVal[$m->primaryKey]];
} else {
$opts['conditions'] = Hash::merge($opts['conditions'], [$m->alias.'.'.$m->primaryKey=>$gemVal[$m->primaryKey]]);
}
if(isset($opts['method'])){
$method = $opts['method'];
} else {
$method = 'first';
}
if($r = $m->request('first', $opts)){
unset($r[$m->alias]);
$gems[$key][$gemKey] = Hash::merge($gems[$key][$gemKey], $r);
}
}
}
}
}
}
}
}
}
}
}
寫一個輔助函數,使調用這個函數有點清潔(PS php5.4 +可以取代數組語法如果使用舊版本的PHP):
查詢現在看起來是這樣的:
$this->Model->find('all', ['drill'=>$this->Model->drill(['Assoc1'=>['SubAssoc1','SubAssoc2'=>['o'=>['conditions'=>'condition', 'fields'=>['fielda', 'fieldb', 'fieldc']], 'SubAssoc3' ]]])]);
助手:
public function drill($array=array(), $first=true){
$drill = [];
foreach($array as $key => $value){
if(is_array($value)){
if(isset($value['o']) && is_array($value['o'])){
foreach($value['o'] as $k => $v){
$drill['drill'][$key][$k] = $v;
}
unset($value['o']);
}
if(!empty($value)){
if(isset($drill['drill'][$key])){
$drill['drill'][$key] = Hash::merge($drill['drill'][$key],$this->drill($value, false));
} else {
$drill['drill'][$key] = $this->drill($value, false);
}
}
} else {
$drill['drill'][] = $value;
}
}
if($first){
return $drill['drill'];
}
return $drill;
}
啊,當然!謝謝!我忘記將可容納行爲附加到我的模型中。我已經完成了所有工作。進一步證明爲什麼你不應該在星期天編碼;) – 2012-03-11 15:55:09