如何在CakePHP中过滤深层关联

如何在CakePHP中过滤深层关联,cakephp,cakephp-1.3,Cakephp,Cakephp 1.3,我有以下表格:活页夹、文档、用户、文档和用户。文档属于活页夹,文档属于任何用户 我想为当前登录的用户(docs\u users表中的关联用户\u id)获取活页夹及其关联文档 我尝试了Containable和find('all')以及连接、条件等,但我不知道如何从Docs\u Users表中未关联的用户中删除文档 此代码不起作用: $binders = $this->Binder->find( 'all', arr

我有以下表格:活页夹、文档、用户、文档和用户。文档属于活页夹,文档属于任何用户

我想为当前登录的用户(docs\u users表中的关联用户\u id)获取活页夹及其关联文档

我尝试了Containable和find('all')以及连接、条件等,但我不知道如何从Docs\u Users表中未关联的用户中删除文档

此代码不起作用:

$binders = $this->Binder->find( 
        'all',                  
        array( 
            'joins' => array(
                array( 
                    'table' => 'binders_users', 
                    'alias' => 'BindersUser', 
                    'type' => 'inner', 
                    'foreignKey' => false, 
                    'conditions'=> array(
                        'BindersUser.binder_id = Binder.id',
                        'BindersUser.user_id = ' . $this->Auth->user('id')
                    )
                ),
                array( 
                    'table' => 'docs', 
                    'alias' => 'Doc', 
                    'type' => 'left', 
                    'foreignKey' => false, 
                    'conditions'=> array(
                        'Doc.binder_id = Binder.id',
                    )
                ),                          
                array( 
                    'table' => 'docs_users', 
                    'alias' => 'DocsUser', 
                    'type' => 'left', 
                    'foreignKey' => false, 
                    'conditions'=> array(
                        'DocsUser.doc_id = Doc.id',
                        'DocsUser.user_id = ' . $this->Auth->user('id')
                    )
                )           
            ),
            'recursive'=>0
        )
    );
$this->set('binders', $binders);
这也不是:

$this->Binder->recursive = 2;
$this->Binder->Behaviors->attach('Containable');
$this->Binder->contain(array(
    'Branch',
    'Doc' => array(                     
        'User' => array(
            'DocsUser' => array(
                'conditions' => array('id = "17"')
            )
        )
    )
));
$binders = $this->Binder->find('all');
任何来自你经验丰富的专业人士的帮助都将是伟大的!谢谢

替代/简化解决方案?

如果我只想获取用户有权限访问的绑定器,那么这个方法就行了。又短又甜。但是,它仍然会发送所有相关的文档,这不是我想要的行为。它只需要传递用户有权限访问的文档(如前所述)


以下是在CakePHP中对数据进行深度查找的几个可用选项:


在这一行中,您需要告诉Cake您谈论的是哪种型号的id:

'conditions' => array('id = "17"')
e、 g.
DocsUser.id


…并且您不会将递归与containable一起使用。摆脱它。

你试过从用户的角度来看问题吗

$this->Binder->Doc->User->Behaviors->attach('Containable');
$this->Binder->Doc->User->contain(array('Doc'=>'Binder'));
$user = $this->Binder->Doc->User->find('all',array('conditions'=>'User.id'=>$user_id));
无论如何都应检测到“DocsUser”关联

也许从装订工的角度来看

在活页夹模型中添加(请检查表、键和模型名称,以防我输入错误)

然后在你的活页夹控制器中尝试

$this->Binder->Behaviors->attach('Containable');
$this->Binder->contain(array('Doc'));
$conditions = array();
$conditions = $this->Binder->getBindersByUserSql($this->Auth->user('id'));
$binders = $this->Binder->find('all',array('conditions'=>$conditions)));

有什么好的吗?

这是我根据收到的所有优秀反馈提出的最终解决方案。我认为这是一个优雅的解决方案,可以在任何需要深度关联的场景中重用

在binder_控制器中,我解除了文档模型的绑定,并使用finderQuery将其绑定回来,以仅选择用户有权查看的文档。然后在binders_users表中,仅选择用户有权访问的Binder

谢谢大家的帮助


有关

的更多信息,如果将
debug
设置为2,并查看生成的查询蛋糕,可能会有所帮助。然后进行必要的更改以获得所需的结果。另外,您可以将DB模式粘贴到pastebin或其他东西上并链接它。好主意。这里是:我现在不使用ACL表,因为我认为在记录级别这样做会创建一个庞大的数据库。如果@Leo的方法不适合你,为什么不把它分成两个查询来获得你想要的确切结果呢?我发现,在使用Cake和$this->find()时,我往往忘记了一个事实,那就是最终都是SQL,而且您总是可以分解问题,而不是在一个查询中完成所有操作:)JohnP-您是对的。我只是不知道如何在CakePHP框架内实现这一点。还是有点绿色。实际上这是由数组树指定的。如果我只是想让它成为一个级别,你是对的,我可以指定Doc.User.Docsuser.id=17,但仍然存在同样的问题。这些都是很好的链接。肯定让我走了这么远。但我不确定他们是否真的回答了这个问题。我认为一些相关的代码在这里会很有帮助。这绝对是正确的。我想问题是,在活页夹的环境中,你是如何做到这一点的?是的。它起作用了。必须做一些更改(字段名),但它可以工作。我不想对礼物吹毛求疵,但你能给我一些提示,告诉我如何显示用户有权限的所有活页夹,以及属于活页夹的、用户有权限的文档。非常感谢你的帮助。超有启发性!权限是如何表示的?
function getBindersByUserSql($user_id)
    {       
        $dbo = $this->getDataSource();
        $subQuery = $dbo->buildStatement(
            array(
                    'fields' => array('DISTINCT(Doc.binder_id)'),
                    'table' => "docs_users",                                       
                    'joins' => array(
                                array('table' => 'users',
                                    'alias' => 'User',
                                    'type' => 'INNER',
                                    'conditions' => array('DocsUser.user_id = User.id')
                                ),
                                array('table' => 'docs',
                                    'alias' => 'Doc',
                                    'type' => 'INNER',
                                    'conditions' => array('Doc.id = DocsUser.doc_id')
                                )
            ),
                    'alias'=>"DocsUser",                                            
                    'conditions' => array("User.id"=>$user_id),
                    'order' => null,
                    'group' => "Doc.binder_id"
                    ),
                    $this
                    );
        return $dbo->expression($subQuery);
    }
$this->Binder->Behaviors->attach('Containable');
$this->Binder->contain(array('Doc'));
$conditions = array();
$conditions = $this->Binder->getBindersByUserSql($this->Auth->user('id'));
$binders = $this->Binder->find('all',array('conditions'=>$conditions)));
$this->Binder->unbindModel(array('hasMany' => array('Doc')));
$this->Binder->bindModel(
    array('hasMany' => array(
            'Doc' => array(
                'className' => 'Doc',
                'foreignKey' => 'binder_id',
                'dependent' => false,
                'finderQuery' => 'SELECT Doc.* FROM docs AS Doc INNER JOIN docs_users AS DocsUser ON DocsUser.doc_id = Doc.id AND DocsUser.user_id = ' . $this->Auth->user('id')
            )
        )
    )
);

$binders = $this->Binder->find( 
    'all',                  
    array( 
        'joins' => array(
            array( 
                'table' => 'binders_users', 
                'alias' => 'BindersUser', 
                'type' => 'inner', 
                'foreignKey' => false, 
                'conditions'=> array(
                    'BindersUser.binder_id = Binder.id',
                    'BindersUser.user_id = ' . $this->Auth->user('id')
                )
            )               
        )
    )
);