我正在尝试获取所有访问者的列表,其中只包含API调用的最新访问信息和相关的VisitType描述,我需要能够在一次查找中执行此操作。以前我们有下面的第二个代码块,但是当访问者有多个关联的访问记录(每个访问记录一个)时,这将为访问者返回多个记录。我只需要获取最新版本(MAX(Visit.visit_date)
但显然无法使用此功能,如果我们打算加入VisitType
)与其关联的VisitType.type_description
。
由于我们正在尝试获取访问者列表,因此beforeFind()函数位于访问者模型上。
当我尝试使用下面的可包含代码时,我得到了以下问题:
Warning (512): Model "Site" is not associated with model "Site" [CORE/Cake/Model/Behavior/ContainableBehavior.php, line 343]
Warning (512): Model "SubjectStatus" is not associated with model "SubjectStatus" [CORE/Cake/Model/Behavior/ContainableBehavior.php, line 343]
我建立了这些协会:
无法包含的代码:
public function beforeFind($options, $primary=false) {
if ($this->__AjaxDataLoad) {
// Replacing a bunch of Model rebinds with Containable
$this->Behaviors->load('Containable');
$this->contain(array(
'Site' => array(
'conditions' => array('Site.id = Visit.site_id'),
'field' => array('Site.site_name')
),
‘VisitorStatus' => array(
'conditions' => array(‘VisitorStatus.id = Visitor.visit_status_id'),
'field' => array(‘VisitorStatus.status')
),
'Visit' => array(
'conditions' => array('Visit.subject_id = Visitor.id'),
'order' => 'Visit.visit_date DESC',
'limit' => 1,
'VisitType' => array(
'conditions' => array('Visit.visit_type_id = VisitType.id'),
'fields' => array('VisitType.type_description'),
)
)
));
}
}
以前,以下代码“有效”,每个访问者包含多行,每次访问一行,这会产生不良副作用:
public function beforeFind($options, $primary=false) {
if ($this->__AjaxDataLoad) {
$this->unbindModelAll();
$this->bindModel(array(
'belongsTo' => array(
'Site' => array(
'className' => 'Site',
'foreignKey' => 'site_id',
),
‘VisitorStatus' => array(
'className' => ‘VisitorStatus',
'foreignKey' => ‘visitor_status_id',
)
),
'hasOne' => array(
'Visit' => array(
'className' => 'Visit',
'foreignKey' => ‘visitor_id',
'order' => 'Visit.visit_date DESC’,
‘limit’ => 1 // <—————————————— THIS DOES NOTHING
),
'VisitType => array(
'foreignKey' => false,
'conditions' => array("Visit.visit_type_id = VisitType.id"),
'fields' => array('VisitType.type_description’)
)
)
));
}
}
我正在尝试的Containable结构有什么问题吗?
我配置了Debug = 2,CakePHP 2.2.5版
答案 0 :(得分:0)
我最终提出的解决方案完全绕过了CakePHP关系技术。它归结为使用virtualFields和子查询作为最后的手段。
public function beforeFind($options) {
if ($this->__AjaxDataLoad) {
$options['joins'] = array(
array(
'table' => 'visits',
'alias' => 'Visit',
'type' => 'LEFT',
'conditions' => array('Visit.visitor_id = Visitor.id')
)
);
$options['group'] = array('Visitor.id');
if (is_null($options['fields'])) {
$options['fields'] = array(
'Visitor.*', 'Site.*', 'VisitorStatus.*'
);
}
$this->virtualFields['last_visit_date'] = 'MAX(Visit.visit_date)';
$this->virtualFields['last_visit_kind'] = 'SELECT visit_kinds.kind FROM visits INNER JOIN visit_kinds ON visits.visit_kind_id = visit_kinds.id WHERE visits.visitor_id=Visitor.id ORDER BY visits.visit_date DESC LIMIT 1';
}
return $options;
}