2

我正在尝试使用 Containable 返回具有多个关联模型(以及那些数据数组)的模型。模型处理测试结果。以下是模型:

楷模:

Question : has and belongs to many Category
Category : has and belongs to many Question
Attempt : has many AttemptedQuestions
AttemptedQuestion : belongs to Question

我想返回一个包含所有 AttemptedQuestions及其相应的问题 + 类别的尝试

所以基本上,关系图是这样的:

Attempt => AttemptedQuestion(s) => Question => Category

我怀疑由于 HABTM 关系,Cake 更愿意返回:

Attempt => AttemptedQuestion(s) => array( Question, Category )<-- 类别不包含在 Question 数组中,而是姐妹。这也很好。

目前,我根本无法让 Category 出现。这是我在控制器中所做的事情(这不会导致类别出现在结果中):

$this->Attempt->contain(array('AttemptedQuestion' => array('Question'=>'Category'))); 
$attempt_to_be_graded = $this->Attempt->findById( $attempt_id );

我究竟做错了什么?

更新 这是基于@nunser 的答案的修订。这也行不通。

$this->Attempt->contain(array('AttemptedQuestion' => array('Question'=>array('Question'=>array('Category') )))); 
$attempt_to_be_graded = $this->Attempt->findById($attempt_id );

这是返回的数据的样子:

array(
    'Attempt' => array(
        'id' => '39',
        ...
    ),
    'AttemptedQuestion' => array(
        (int) 0 => array(
            'id' => '189',
            ...,
            'Question' => array(
                'id' => '165',
                ...
            )
        ),
        (int) 1 => array(
            'id' => '188',
            ...,
            'Question' => array(
                'id' => '164',
                ...
            )
        )

    )
)

更新 2

我仍在为此苦苦挣扎,但我认为我的关联必须是正确的,因为以下内容按预期返回了我所有类别的列表:

$categories = $this->Attempt->AttemptedQuestion->Question->Category->find('all');

更新 3

$this->Question->find('first')通过测试整个代码中各个点的结果,我缩小了这个问题的范围。看来结果是预期的,直到这之后:$test = $this->Test->findById($test_id);.

这是演示的代码:

    $this->loadModel('Question');       
    $test = $this->Question->find('first');
    debug($test);
//THESE RESULTS INCLUDE Category DATE

    $test = $this->Test->findById($test_id);

    $this->loadModel('Question');       
    $test = $this->Question->find('first');
    debug($test);
    exit;
//THESE RESULTS DO NOT INCLUDE Category DATE

因此,由于我完全不明白的原因,干预Test->find()似乎阻止了类别数据随后出现。很奇怪吧?

4

4 回答 4

1

HABTM 头痛

这些在 Cake 中很难管理。我开始做的事情被称为“hasMany Threw”,这本书在此处进行了描述

优点是可以更好地控制查找查询。它需要额外Model添加,但这是值得的。CakePHP 中对 HABTM 的自动处理通常很难理解。使用关联来明确定义关系更加灵活。

循环参考

您的模型当前设置有循环引用,这对于 HABTM 可能是有问题的。

Question : has and belongs to many Category
Category : has and belongs to many Question

在 Cake 中很难在两个模型上创建一个 HABTM。通常这只在其中一个上完成,我会选择Question. 使用“hasMany Threw”会更容易。

扔了很多

如果我们使用“hasMany Threw”,那么可包含规则变得更容易解释。

Question : hasMany QuestionCategory
Category : hasMany QuestionCategory
QuestionCategory : belongs to Question, belongs to Category.
Attempt : belongs to Question

现在,我删除了AttamptedQuestion. 我不确定您要建模什么,但是如果一个人可以为每个问题创建多个尝试,那么就不需要了。只需创建一个以上的尝试记录。

查找尝试的所有记录

Attempt使用find 查找所有关联记录Containable如下。

$this->Attempt->find('first',array(
    'conditions'=>array('Attempt.id'=>$attempt_id),
    'contain'=>array(
        'Question'=>array(
            'QuestionCategory'=>array(
                'Category'=>array()
            )
        )
    ));

您仍然可以重新添加AttemptedQuestion模型,并在之前包含它Question

具有关联的不明确的字段名

你应该养成使用Attempt.idin 条件而不是仅仅使用id. 当您使用关联时,SQL 结果中经常会出现重复的字段名。您需要澄清您指的是哪些,因为如果使用 a ,您也可以将Question.id其作为条件。所以它本身就是模棱两可的。AttemptJOINid

于 2013-06-05T19:56:23.963 回答
1

提供有关触发问题的新信息。

$this->loadModel('Question');       
$test = $this->Question->find('first');
debug($test);
//THESE RESULTS INCLUDE Category DATE

$test = $this->Test->findById($test_id);

$this->loadModel('Question');       
$test = $this->Question->find('first');
debug($test);
exit;
//THESE RESULTS DO NOT INCLUDE Category DATE

在上面的场景中,findById魔术函数(这就是我所说的)调用较低级别的数据源驱动程序来执行查询。

DboSource.php它没有使用Containable行为来控制递归,并recursiveModel. 我认为这是造成Containable行为问题的原因。

您可以通过recursivefindById.

$test = $this->Test->findById($test_id);
$this->Test->recursive = 1;

$this->loadModel('Question');       
$test = $this->Question->find('first');
debug($test);
exit;

我猜这可以解决问题,但是您必须记住在使用findById或任何其他魔术功能后将其重置。

如果它是可重现的,则应将其作为错误报告给 Cake 开发人员。

编辑:

递归默认是 1 而不是 0。

于 2013-06-07T16:53:58.000 回答
1

有时,在我这边最好使用嵌套的 binModel 而不是行为,原因是更可配置,请检查此链接,您可能可以帮助您解决问题

CakePHP - 构建一个复杂的查询

cakephp 在一个连接表中一次连接超过 2 个表

于 2013-06-05T16:26:21.267 回答
0

尝试

$this->Attempt->find('first', array('conditions'=>array('id'=>$attempt_id),
                                'contain'=>array('AttemptedQuestion'=> 
                                               array('Question' => 
                                                  array('Category')
                                               )
                                )));
于 2013-06-05T16:22:55.023 回答