尝试用Containable替换CakePHP模型绑定不起作用

时间:2014-01-23 00:55:17

标签: php cakephp cakephp-2.2 containable

我正在尝试获取所有访问者的列表,其中只包含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]

我建立了这些协会:

  • 访客有多次访问,访问有一位访客
  • 访客拥有一个网站,一个网站拥有多个访客
  • VisitorStatus拥有多个访问者,访问者所属于VisitorStatus
  • 访问hasOne VisitKind,VisitKind hasMany Visits

无法包含的代码:

  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版

1 个答案:

答案 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;
  }
相关问题