CakePHP 中的多级模型关联
Posted
技术标签:
【中文标题】CakePHP 中的多级模型关联【英文标题】:Multi-level Model associations in CakePHP 【发布时间】:2012-03-27 20:24:12 【问题描述】:我正在使用 Cakephp 构建一个电子学习网站,其中包含以下模型:课程、测试、问题、答案等。
这是我的联想:
课程有很多测试 测试属于课程 问题属于测试 问题有很多答案 答案属于问题这种模型关联在大多数情况下都能正常工作。例如,Course 的烘焙 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 处停止,并且不会为 Question(s) 提取相关的 Answer(s)。
我通过更改 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] =>
)
)
)
)
)
这适用于我必须完成的工作,但对我来说似乎很难看。如您所见,答案已加载,但我现在也有重复的信息,因为当它加载问题模型时,它会拉入相关的测试。而且我很确定这不符合 CakePHP 约定...
有没有更好的方法来做到这一点? CakePHP 是否只为模型关联建立关联数据数组到一定级别然后停止?
附:我尝试添加:
var $uses = array('Test', 'Question', 'Answer');
...到我的 TestsController 的顶部,但它没有解决问题并且似乎没有任何效果。
必须有更好的方法让 CakePHP 加载所有相关的数据模型以及它们的关联......
【问题讨论】:
【参考方案1】:使用 CakePHP 的可包含行为: http://book.cakephp.org/1.3/view/1323/Containable
我认为对于您的具体情况,查询看起来像:
$this->Test->find('all', array(
'contain'=>array('Question')
)
);
您还可以使用条件、排序等。
【讨论】:
该查询对我来说也没有任何改变。结果 $test 仍然只有问题,没有答案。我查看了您发送的链接并尝试了这个:$test = $this->Test->find('all', array('contain' => array('Question' => array('Answer'))));
这也不起作用。我也试过只输入'contain'=>array('Answer')
,但这不起作用
错误是什么?此外,这取决于您的 CakePHP 版本 - 在某些早期版本中,您可能必须显式添加 Containable 行为。【参考方案2】:
我使用了似乎可以做到的递归属性。
$test = $this->Test->find('all', array('recursive' => 2));
告诉 CakePHP 加载另一个级别的关联,因此结果不仅包括问题,还包括相关的答案。
【讨论】:
是的,也可以。对于大型查询和大量记录,它的效率会有点低,因为它可以有效地获取所有内容,但对于小型查询应该没问题。以上是关于CakePHP 中的多级模型关联的主要内容,如果未能解决你的问题,请参考以下文章