CakePHP中的多级模型关联

时间:2012-03-27 20:24:13

标签: cakephp

我正在CakePHP中建立一个电子教学网站,其中包含模型:课程,测试,问题,答案等。

以下是我的协会:

  • 课程有多次测试
  • 测试所属课程
  • 问题belongsTo Test
  • 问题有很多答案
  • 答案属于问题

此模型关联在大多数情况下都能正常工作。例如,课程的烘焙CRUD操作知道有属于它的测试,问题知道他们有相关的答案等...

但是我正在尝试编写一个在TestsController中运行的测试管理工具,并且关联级别在Question处结束。没有答案。换句话说,我正在处理的视图默认来自烘焙的TestsController:

Array
(
[Test] => Array
    (
        [id] => 1
        [name] => Test 1
        [course_id] => 1
        [time_limit] => 30
        [max_questions] => 20
        [randomize_order] => 1
        [num_questions] => 2
    )

[Course] => Array
    (
        [id] => 1
        [course_identifier] => TLE1001
        [title] => Child Development I
        [description] => 
    )

[Question] => Array
    (
        [0] => Array
            (
                [id] => 1
                [text] => What is your name?
                [test_id] => 1
                [order] => 0
            )

        [1] => Array
            (
                [id] => 2
                [text] => What is my name?
                [test_id] => 1
                [order] => 0
            )

    )

)

如您所见,我视图中的$ test数组在Question处停止,并且没有提取问题的相关答案。

我通过在TestsController中更改“视图”操作的底部来修复此问题:

$test = $this->Test->read(null, $id);
$test['Question'] = $this->Test->Question->find('all'); //I added this line...
$this->set('test', $test);

我添加了中间行,因此在为要使用的视图设置$ test数组之前,它会手动替换$ test ['Question']的所有内容。

结果如下:

Array
(
[Test] => Array
    (
        [id] => 1
        [name] => Test 1
        [course_id] => 1
        [time_limit] => 30
        [max_questions] => 20
        [randomize_order] => 1
        [num_questions] => 2
    )

[Course] => Array
    (
        [id] => 1
        [course_identifier] => TLE1001
        [title] => Child Development I
        [description] => The first years of life offer a window of opportunity for a child’s development. A solid understanding of how children grow and develop is essential to providing a quality care environment.
    )

[Question] => Array
    (
        [0] => Array
            (
                [Question] => Array
                    (
                        [id] => 1
                        [text] => What is your name?
                        [test_id] => 1
                        [order] => 0
                    )

                [Test] => Array
                    (
                        [id] => 1
                        [name] => Test 1
                        [course_id] => 1
                        [time_limit] => 30
                        [max_questions] => 20
                        [randomize_order] => 1
                        [num_questions] => 2
                    )

                [Answer] => Array
                    (
                        [0] => Array
                            (
                                [id] => 1
                                [question_id] => 1
                                [text] => My name is what I say it is.
                                [correct] => 1
                            )

                        [1] => Array
                            (
                                [id] => 2
                                [question_id] => 1
                                [text] => My name is Earl.
                                [correct] => 
                            )

                    )

            )

        [1] => Array
            (
                [Question] => Array
                    (
                        [id] => 2
                        [text] => What is my name?
                        [test_id] => 1
                        [order] => 0
                    )

                [Test] => Array
                    (
                        [id] => 1
                        [name] => Test 1
                        [course_id] => 1
                        [time_limit] => 30
                        [max_questions] => 20
                        [randomize_order] => 1
                        [num_questions] => 2
                    )

                [Answer] => Array
                    (
                        [0] => Array
                            (
                                [id] => 3
                                [question_id] => 2
                                [text] => None of your business
                                [correct] => 1
                            )

                        [1] => Array
                            (
                                [id] => 4
                                [question_id] => 2
                                [text] => Jim
                                [correct] => 
                            )

                    )

            )

    )

)

这对我必须完成的工作有效,但对我来说似乎很难看。正如您所看到的,Answer(s)已加载,但我现在也有重复信息,因为当它加载问题模型时,它会拉入相关的测试。而且我很确定这与CakePHP约定不相符......

有更好的方法吗? CakePHP是否只为模型关联构建关联数据数组,然后停止?

P.S。我试着添加:

var $ uses = array('Test','Question','Answer');

...到我的TestsController的顶部,但它没有解决问题,似乎没有效果。

必须有更好的方法让CakePHP加载所有相关的数据模型和他们的关联......

2 个答案:

答案 0 :(得分:2)

使用CakePHP的可包含行为: http://book.cakephp.org/1.3/view/1323/Containable

我认为对于您的具体情况,查询将如下所示:

$this->Test->find('all', array(
    'contain'=>array('Question')
    )
);

您还可以使用条件,订购等。

答案 1 :(得分:1)

我使用了似乎这样做的递归属性。

$test = $this->Test->find('all', array('recursive' => 2));

告诉CakePHP加载另一级别的关联,因此结果不仅包括问题,还包括相关的答案。