Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
CakePHP:使用多级可包含行为_Php_Cakephp_Behavior - Fatal编程技术网

CakePHP:使用多级可包含行为

CakePHP:使用多级可包含行为,php,cakephp,behavior,Php,Cakephp,Behavior,我已经花了相当长的时间尝试在CakePHP中使用可包含的行为,但我无法让它像我预期的那样工作 我的应用程序不同,但为了简化,我将举这个例子。比如说,我有一个论坛,里面有线程和活动,活动可以分级。一般关系将是: 论坛:有许多[线程] 线程:属于[论坛],有许多[活动] 活动:属于[Thread],有许多[Rating] 评级:属于[活动] 我想要实现的是,使用find方法,获得某个论坛上的所有评分。我认为应该做的是: $this->Rating->find('count', arra

我已经花了相当长的时间尝试在CakePHP中使用可包含的行为,但我无法让它像我预期的那样工作

我的应用程序不同,但为了简化,我将举这个例子。比如说,我有一个论坛,里面有线程和活动,活动可以分级。一般关系将是:

论坛:有许多[线程]
线程:属于[论坛],有许多[活动]
活动:属于[Thread],有许多[Rating]
评级:属于[活动]

我想要实现的是,使用find方法,获得某个论坛上的所有评分。我认为应该做的是:

 $this->Rating->find('count', array(
    'contain' => array(
        'Activity' => array(
            'Thread'
        )
    ),
    'conditions' => array(
        'Thread.forum_id' => 1
    )
));
但查询的结果是:

SELECT COUNT(*) AS `count` FROM `ratings` AS `Rating` LEFT JOIN `activities` AS `Activity` ON (`Rating`.`activity_id` = `Activity`.`id`) WHERE `Thread`.`forum_id` = 1;
我已经使用“连接”选项完成了这项操作,但是它更复杂,我必须在许多情况下使用这种操作

与示例相关的所有文件都可以在此处找到:

谢谢

2011年11月23日更新

在调查了框架之后,感谢Moz Morris和api55的回答,我找到了问题的根源

基本问题是,正如我所理解的CakePHP,我认为它每次都在使用连接进行查询。它不这样做的事情,它将执行的实际操作,以获得我想要的结果,将是这样的:

SELECT * FROM Rating JOIN Activity...
SELECT * FROM Activity JOIN Thread...
SELECT * FROM Activity JOIN Thread...
...
这意味着它将执行一个查询以获取所有活动,然后针对每个活动执行一个查询以获取线程。。。我的方法之所以失败,不是因为Containable行为使用错误,而是因为“conditions”选项应用于所有查询,在第一个查询中,由于缺少线程表,它崩溃了。找到这一点后,有两种可能的解决方案:

  • 正如api55所说,使用“contain”数组中的条件,它只会将它们应用于使用Thread表的查询。但这样做的问题仍然存在,因为我们有太多的查询

  • 正如Moz Morris所说,将线程模型与评级绑定也会起作用,它将执行一个查询,这正是我们想要的。问题是,我认为这是一个跳过模型之间关系的补丁,不遵循CakePHP哲学


我将api55解决方案标记为正确,因为它解决了我遇到的具体问题,但两者都给出了问题的解决方案。

首先,您是否已将actAs containable变量放入appModel中??如果没有它,这个beahaviour将根本无法工作(我看到它无法正常工作,因为它没有与线程表连接)

我会从上面做,我的意思是从论坛,所以你选择你的论坛(我不确定你想要论坛或线程)并获得它的所有评级,如果没有评级,你将以评级键为空结束

像这样的

'contain' => array(
    'Activity' => array(
        'Thread' => array(
              'conditions' => array('Thread.forum_id' => 1)
         )
    )
),
应用模型

public $actsAs = array('Containable');
额定值控制器

 $this->Rating->Activity->Thread->Forum->find('count', array(
    'contain' => array(
        'Thread' => array(
             'Activity' => array(
                 'Rating' => array (
                       'fields' => array ( 'Rating.*' )
                  )
              )
        )
    ),
    'conditions' => array(
        'Forum.id' => 1
    )
));
然后,若您只需要评级表中的一个值,那个么只需使用Set:extract来获取该值的数组

正如你所做的那样,它无论如何都应该有效,但我建议不要在那里使用论坛id,而是在这样的条件下使用

'contain' => array(
    'Activity' => array(
        'Thread' => array(
              'conditions' => array('Thread.forum_id' => 1)
         )
    )
),

另外,永远不要忘记使用可包含行为(或应用程序内模型)的模型中的actsAs变量。

尽管我喜欢api55的解决方案,但我认为结果有点混乱-这取决于您打算对数据做什么,我猜

我假设当你说使用“连接”方法时,你说的是使用这个方法:

$this->Rating->bindModel(array(
  'belongsTo' => array(
    'Thread' => array(
      'foreignKey' => false,
      'conditions' => 'Thread.id = Activity.thread_id',
    ),
    'Forum' => array(
      'foreignKey' => false,
      'conditions' => 'Forum.id = Thread.forum_id'
    )
  )
));

$ratings = $this->Rating->find('all', array(
  'conditions' => array(
    'Forum.id' => 1 // insert forum id here
  )
));

这对我来说似乎有点干净,您不必担心在应用程序模型中使用可包含的行为。值得考虑。

在线程数组中移动“条件”将不起作用,因为其他所有内容的结果仍将返回,而“线程”数组为空。@MozMorris这是真的,因为它是左连接。。。但是,如果他从顶部运行它(从论坛/线程),它将获得所有评级或为空,尽管它会有很多恼人的树(我通常使用可链接的行为),谢谢回复。我在链接上提供的代码上尝试了这一点,查询是
选择COUNT(*)AS COUNT FROM AS Forum AS Forum WHERE Forum.id=1
。我已经在AppModel和所有东西上设置了可控制的行为。我不知道我是否有一些配置问题或其他问题,但它似乎工作不正常。@Noeldmartin要100%确保您正确加载行为,您可以在控制器中编写以下代码
$this->Rating->Behaviors->attach('Containable')这是用于测试目的。。。如果你在论坛中调用find do
$this->Rating->Activity->Thread->Forum->behavies->attach('Containable')
@api55我已经用最终的解决方案更新了问题,谢谢你的回答,它帮助我找到了问题。如果你需要计数,那么很明显,只需将“all”替换为“count”。)我从来没有想过XD,但它确实更干净,另一种方式会产生许多递归…谢谢你的回答,这在这个例子中是可行的。问题是,在实际应用程序中,我必须多次这样做,并且我希望做得更模块化(使用带有“启用”模型的阵列)。按照你说的做,我每次都应该设置所有的条件。此外,它不起作用让我很烦,这就是可控制行为的目的,我不知道我是否遗漏了什么。无论如何谢谢你。