如何在多个“ with”查询中重用Yii1条件?

时间:2019-06-21 20:11:21

标签: php mysql yii orm

首先让我介绍一下数据库结构enter image description here 结构的顶部是Scope。它为HAS_MANY Topics
Topic HAS_MANY ProblemsPresets
PresetsProblems通过MANY_TO_MANY相关。
Groups可被视为描述用户有权访问Problems的内容的访问规则。

我尝试在单个查询中为一组Scopes建立数据树(Topics-> Groups-> ...)。数据应包含Problems,它属于确定的Groups或根本不属于组(例如,匿名用户没有安全级别)。

一些关于Presets的词。该实体用于为前端创建一些作业。几个Presets可能在同一Problems下包含相同的Topic。此信息对于了解我的查询出了什么问题很有用;

首先,我为Problem创建了一个范围 allowedForUser ,该范围对于使Problems用户具有访问权限很有用;

public function allowedForUser($user) {

    /* some stuff to get group id list for user */                                                        

    return $this->allowedForGroupsAndGuests($user_group_ids);  
}                                                              
/**                                                                    
 * Scope - allowed to groups and all                                   
 *                                                                     
 * @param $group_ids                                                   
 * @return $this                                                       
 */                                                                    
public function allowedForGroupsAndGuests($group_ids) {                
    $this->allowedForGroups($group_ids);                               

    $criteria_no_group = new CDbCriteria();                            
    $criteria_no_group->addCondition('group_id is NULL');              

    $this->getDbCriteria()->mergeWith(array(                           
        'with' => array(                                               
            'groups' => $criteria_no_group->toArray()                  
        )                                                              
    ), 'OR');                                                          

    return $this;                                                      
}                                                                      

/**                                                                    
 * Scope - allowed to groups                                           
 *                                                                     
 * @param $group_ids                                                   
 * @return $this                                                       
 */                                                                    
public function allowedForGroups($group_ids) {                         
    // select allowed by groups                                        
    $criteria_by_group = new CDbCriteria();                            
    $criteria_by_group->addInCondition('group_id', $group_ids);        

    $this->getDbCriteria()->mergeWith(array(                           
        'with' => array(                                               
            'groups' => $criteria_by_group->toArray()                  
        )                                                              
    ));                                                                

    return $this;                                                      
}                                                                      

如上所述,我需要从作用域开始获取一棵完整的树。因此,我为Scope创建了一个范围:

/**                                                                               
 * Scope to get problem scopes with problems and topics with allowed problems only
 *                                                                                
 * @param $user                                                                   
 * @return $this                                                                  
 */                                                                               
public function availableForUser($user) {                                         
    $this->getDbCriteria()->mergeWith(array(                                      
        'with' => array(                                                          
            'topics' => array(                                                    
                'with' => array(                                                  
                    'problems' => array(                               
                        'scopes' => array(                                        
                            'allowedForUser' => $user,                            
                        )                                                         
                    )                                                             
                )                                                                 
            )                                                                     
        )                                                                         
    ));                                                                           

    return $this;                                                                 
}                                                                                                                                                                

在这里,我要做的就是打电话给

ProblemScope::model()->availableForUser($user)->findAll()

...,所有树都在这里:Scopes,它们的TopicsProblems对于当前用户;按计划不存在空白的ScopesTopics。 但是根本没有Presets,因此我认为很容易解决扩展范围标准的问题:

public function availableForUser($user) {
        $this->getDbCriteria()->mergeWith(array(
            'with' => array(
                'topics' => array(
                    'with' => array(
                        'problems' => array(
                            'scopes' => array(
                                'allowedForUser' => $user,
                            )
                        ),
                        'problemPresets' => array(
                            'with' => array(
                                'problems' => array(
                                    'alias' => 'presetproblems',
                                    'scopes' => array(
                                        'allowedForUser' => $user,
                                    )
                                )
                            )
                        )
                    )
                )
            )
        ));

        return $this;
    }

在这里我遇到了困难:语法错误或访问冲突:1066不是唯一的表/别名:'groups_groups'

SELECT t.id AS t0_c0,
       t.title AS t0_c1,
       t.description_info AS t0_c2,
       t.sort_order AS t0_c3,
       topics.id AS t1_c0,
       topics.title AS t1_c1,
       topics.description_info AS t1_c2,
       topics.scope_id AS t1_c3,
       problems.id AS t2_c0,
       problems.title AS t2_c1,
       problems.description_info AS t2_c2,
       problems.topic_id AS t2_c3,
       groups.id AS t3_c0,
       groups.name AS t3_c1,
       groups.comment AS t3_c2,
       groups.access_files AS t3_c3,
       groups.access_handbook AS t3_c4,
       groups.access_lessons AS t3_c5,
       groups.access_course AS t3_c6,
       groups.access_uchebnik AS t3_c7,
       problemPresets.id AS t4_c0,
       problemPresets.title AS t4_c1,
       problemPresets.topic_id AS t4_c2,
       presetproblems.id AS t5_c0,
       presetproblems.title AS t5_c1,
       presetproblems.description_info AS t5_c2,
       presetproblems.topic_id AS t5_c3,
       groups.id AS t6_c0,
       groups.name AS t6_c1,
       groups.comment AS t6_c2,
       groups.access_files AS t6_c3,
       groups.access_handbook AS t6_c4,
       groups.access_lessons AS t6_c5,
       groups.access_course AS t6_c6,
       groups.access_uchebnik AS t6_c7
FROM cp_problem_scopes t
LEFT OUTER JOIN cp_problem_scope_topics topics ON (topics.scope_id=t.id)
LEFT OUTER JOIN cp_problems problems ON (problems.topic_id=topics.id)
LEFT OUTER JOIN cp_problem_group groups_groups ON (problems.id=groups_groups.problem_id)
LEFT OUTER JOIN cp_groups groups ON (groups.id=groups_groups.group_id)
LEFT OUTER JOIN cp_problem_presets problemPresets ON (problemPresets.topic_id=topics.id)
LEFT OUTER JOIN cp_problem_preset_problem problems_presetproblems ON (problemPresets.id=problems_presetproblems.preset_id)
LEFT OUTER JOIN cp_problems presetproblems ON (presetproblems.id=problems_presetproblems.problem_id)
LEFT OUTER JOIN cp_problem_group groups_groups ON (presetproblems.id=groups_groups.problem_id)
LEFT OUTER JOIN cp_groups groups ON (groups.id=groups_groups.group_id)
WHERE ((group_id IN (:ycp4,
                     :ycp5,
                     :ycp6,
                     :ycp7))
       OR (group_id IS NULL))
  AND ((group_id IN (:ycp8,
                     :ycp9,
                     :ycp10,
                     :ycp11))
       OR (group_id IS NULL))

可以解决“问题”范围并为其固定别名的问题:

public function availableForUser($user) {                                         
    $problems_criteria = Problem::model()->allowedForUser($user)->getDbCriteria();

    $problems_criteria->alias = 'topic_problems';                                 
    $problems_criteria->with['groups']['alias'] = 'topic_problems_groups';        
    $topic_problems_criteria_arr = $problems_criteria->toArray();                 

    $problems_criteria->alias = 'topic_presets_problems';                         
    $problems_criteria->with['groups']['alias'] = 'topic_presets_problems_groups';
    $topic_presets_problems_criteria_arr = $problems_criteria->toArray();         

    $this->getDbCriteria()->mergeWith(array(                                      
        'with' => array(                                                          
            'topics' => array(                                                    
                'with' => array(                                                  
                    'problems' => $topic_problems_criteria_arr,                   
                    'problemPresets' => array(                                    
                        'with' => array(                                          
                            'problems' => $topic_presets_problems_criteria_arr    
                        )                                                         
                    )                                                             
                )                                                                 
            )                                                                     
        )                                                                         
    ));                                                                           

    return $this;                                                                 
}                                                                                 

看上去很糟糕,但问题已解决。引入了新的内容:where子句中的列'group_id'不明确。

SELECT `t`.`id` AS `t0_c0`,
       `t`.`title` AS `t0_c1`,
       `t`.`description_info` AS `t0_c2`,
       `t`.`sort_order` AS `t0_c3`,
       `topics`.`id` AS `t1_c0`,
       `topics`.`title` AS `t1_c1`,
       `topics`.`description_info` AS `t1_c2`,
       `topics`.`scope_id` AS `t1_c3`,
       `topic_problems`.`id` AS `t2_c0`,
       `topic_problems`.`title` AS `t2_c1`,
       `topic_problems`.`description_info` AS `t2_c2`,
       `topic_problems`.`topic_id` AS `t2_c3`,
       `topic_problems_groups`.`id` AS `t3_c0`,
       `topic_problems_groups`.`name` AS `t3_c1`,
       `topic_problems_groups`.`comment` AS `t3_c2`,
       `topic_problems_groups`.`access_files` AS `t3_c3`,
       `topic_problems_groups`.`access_handbook` AS `t3_c4`,
       `topic_problems_groups`.`access_lessons` AS `t3_c5`,
       `topic_problems_groups`.`access_course` AS `t3_c6`,
       `topic_problems_groups`.`access_uchebnik` AS `t3_c7`,
       `problemPresets`.`id` AS `t4_c0`,
       `problemPresets`.`title` AS `t4_c1`,
       `problemPresets`.`topic_id` AS `t4_c2`,
       `topic_presets_problems`.`id` AS `t5_c0`,
       `topic_presets_problems`.`title` AS `t5_c1`,
       `topic_presets_problems`.`description_info` AS `t5_c2`,
       `topic_presets_problems`.`topic_id` AS `t5_c3`,
       `topic_presets_problems_groups`.`id` AS `t6_c0`,
       `topic_presets_problems_groups`.`name` AS `t6_c1`,
       `topic_presets_problems_groups`.`comment` AS `t6_c2`,
       `topic_presets_problems_groups`.`access_files` AS `t6_c3`,
       `topic_presets_problems_groups`.`access_handbook` AS `t6_c4`,
       `topic_presets_problems_groups`.`access_lessons` AS `t6_c5`,
       `topic_presets_problems_groups`.`access_course` AS `t6_c6`,
       `topic_presets_problems_groups`.`access_uchebnik` AS `t6_c7`
FROM `cp_problem_scopes` `t`
LEFT OUTER JOIN `cp_problem_scope_topics` `topics` ON (`topics`.`scope_id`=`t`.`id`)
LEFT OUTER JOIN `cp_problems` `topic_problems` ON (`topic_problems`.`topic_id`=`topics`.`id`)
LEFT OUTER JOIN `cp_problem_group` `groups_topic_problems_groups` ON (`topic_problems`.`id`=`groups_topic_problems_groups`.`problem_id`)
LEFT OUTER JOIN `cp_groups` `topic_problems_groups` ON (`topic_problems_groups`.`id`=`groups_topic_problems_groups`.`group_id`)
LEFT OUTER JOIN `cp_problem_presets` `problemPresets` ON (`problemPresets`.`topic_id`=`topics`.`id`)
LEFT OUTER JOIN `cp_problem_preset_problem` `problems_topic_presets_problems` ON (`problemPresets`.`id`=`problems_topic_presets_problems`.`preset_id`)
LEFT OUTER JOIN `cp_problems` `topic_presets_problems` ON (`topic_presets_problems`.`id`=`problems_topic_presets_problems`.`problem_id`)
LEFT OUTER JOIN `cp_problem_group` `groups_topic_presets_problems_groups` ON (`topic_presets_problems`.`id`=`groups_topic_presets_problems_groups`.`problem_id`)
LEFT OUTER JOIN `cp_groups` `topic_presets_problems_groups` ON (`topic_presets_problems_groups`.`id`=`groups_topic_presets_problems_groups`.`group_id`)
WHERE ((group_id IN (:ycp4,
                     :ycp5,
                     :ycp6,
                     :ycp7))
       OR (group_id IS NULL))
  AND ((group_id IN (:ycp4,
                     :ycp5,
                     :ycp6,
                     :ycp7))
       OR (group_id IS NULL))

最后一个WHERE子句使group_id检查加倍,使我认为我从根本上做错了;我该如何解决该问题?

0 个答案:

没有答案