Yii CActiveRecord多级(嵌套)连接

时间:2014-03-22 23:41:14

标签: php database activerecord yii

我是Yii的新手,到目前为止,我已经设法独自完成但现在我被卡住了。

我有一个复杂的关系数据库(在MySQL中实现)。我有他们的模型并且它正常工作我唯一的问题是我无法弄清楚如何使用CDbCriteria进行复杂查询

该应用程序就像一个问题跟踪器,因此用户可以报告一些问题,负责此类问题的人将与他/她联系。

与问题相关的主要表格:

  • 角色(可以为用户分配多个角色,例如角色可以是“会计师”或“开发人员”)
  • issuetypes(具有角色的用户/例如会计/可以使用一组问题类型创建新问题/例如,#34;打印机问题" /
  • 问题(每个问题只能有一个问题类型)

开发人员可以创建类似"需要新的PHP版本的问题"但是会计师不能那样做,所以我需要在数据库中查询一组角色的所有可用的issuetypes。 如果用户有多个角色(开发人员,测试人员),那么我需要为这些角色提供的issuetypes的联合。 到目前为止它还在工作,但是当我需要更进一步并查询用这些类型提交的所有问题时......我被卡住了。

我需要获得以下查询:

SELECT DISTINCT i.* FROM `issue` i
    LEFT JOIN issuetype ON issuetype.id=i.issuetype_id
    RIGHT JOIN role_has_issuetype rit ON rit.issuetype_id=issuetype.id
    RIGHT JOIN role ON role.id=rit.role_id
WHERE role.role IN ('developer','tester') AND i.id IS NOT NULL

我知道我可以直接使用SQL查询但是db后端将来会更改(最有可能是Oracle)所以我希望尽可能地保留抽象以避免更改任何硬编码SQL语句和"后端独立"。

模型的相关部分:

class Role extends CActiveRecord
{
    public function relations()
    {
        return array(
            'issuetypes' => array(self::MANY_MANY, 'Issuetype', 'role_has_issuetype(role_id, issuetype_id)'),
            'users' => array(self::MANY_MANY, 'User', 'user_has_role(role_id, user_id)'),
        );
    }
}

class Issuetype extends CActiveRecord
{
    public function relations()
    {
        return array(
        ...
        'issues' => array(self::HAS_MANY, 'Issue', 'issuetype_id'),
        'roles' => array(self::MANY_MANY, 'Role', 'role_has_issuetype(issuetype_id, role_id)'),
    );
}

class Issue extends CActiveRecord
{
    public function relations()
    {
        ...
        'issuetype' => array(self::BELONGS_TO, 'Issuetype', 'issuetype_id'),            
    );
    }
}

我尝试过这样的事情:

Issue::model()->with(
array(
    'issuetype'=>array(
     'select'=>false,
     'joinType'=>'INNER JOIN',
     'condition'=>'issuetype.roles IN ("developer","tester")',
)))->findAll();

它很有效,因为issuetype没有列roles它只是一种关系。

我试图分两步完成。首先获取与角色关联的issuetypes然后得到问题。

第一部分是使用此代码:

$crit = new CDbCriteria();
$crit->addInCondition('roles.role',array('developer','tester'));
$crit->select = array('id');
$res=Issuetype::model()->with('roles')->findAll($crit);

但我不知道如何在另一个标准中使用$res。 (我甚至不确定这种方法是否有效,即使它远非最佳)

我已经阅读了十几个SO答案,并与Yii文档一起阅读了Yii论坛,但我发现的例子不足以解决这个问题(至少我不能采用这些答案)代码 我的问题)

我很确定我只是忽略了一些显而易见的东西,但不幸的是我无法自己解决这个问题。

由于

1 个答案:

答案 0 :(得分:1)

睡觉问题有帮助:)

我意识到自己的错误。我应该写这个:

return Issue::model()->with(array(
                            'issuetype.roles'=>array(
                                'select'=>false,
                                'joinType'=>'INNER JOIN',
                                'condition'=>"roles.role IN ('developer','tester')",
                            )))->findAll();

我希望这将有助于将来。