我使用Kohana几个星期了。我注意到的一件事是Kohana缺少急切的装载(据我所知)。假设我有以下表格。
受试者
id
name
章节
id
subject_id
name
画
id
chapter_id
name
当用户打开主题页面时,我想显示所有章节和视频。使用ORM,我可以做到
$tutorials = ORM::factory('subject')->where('id','=', 1)->find();
foreach($tutorials as $tutorial)
{
$chapters = $tutorial->chapters->find_all();
foreach($chapters as $chapter)
{
$videos = $chapter->videos->find_all();
}
}
上面的代码效率不高,因为它会进行太多查询。
我考虑过使用 join 或数据库查询构建器,但它们都没有返回模型对象作为结果。我也查看 with(),但看起来它只适用于一对一的关系。
在ORM对象上使用join会返回一个OPM对象,但它不会从连接表中返回数据。
这里最好的选择是什么?我想最小化查询次数,并希望获得ORM对象的结果。无论它是什么,都应该返回教程,章节和视频中的所有专栏。
答案 0 :(得分:3)
首先,您的代码过多。 ORM方法find()返回1个Model_Subject对象。参见
$chapters = ORM::factory('subject', 1)->chapters->find_all();
foreach($chapters as $chapter)
{
$videos = $chapter->videos->find_all();
}
使用DB构建器,您只需提出2个请求。首先得到所有章节ID的数组:
$chapters = DB::select('id')
->from('chapters')
->where('subject_id', '=', '1')
->execute()
->as_array(NULL, 'id');
其次 - 通过ID获取所有视频作为Model_Video对象
$videos = DB::select('id')
->from('videos')
->where('chapter_id', 'IN', $chapters)
->as_object('Model_Video')
->execute()
->as_array();
答案 1 :(得分:1)
所以我想你想要这样的东西。
$videos = ORM::factory('Video')
->join(array('chapters', 'chapter'), 'LEFT')->on('video.chapter_id', '=', 'chapter.id')
->join(array('subjects', 'subject'), 'LEFT')->on('chapter.subject_id', '=', 'subject.id')
->where('subject.id', '=', $id)
->find_all();
考虑一下,如果视频belongs_to
章belongs_to
主题,请使用with()
尝试以下内容:
$videos = ORM::factory('Video')
->with('chapter:subject') // These are the names of the relationships. `:` is separator
// equals $video->chapter->subject;
->where('subject.id', '=', $id)
->find_all();
通过这样的事情,往往有助于思考“倒退”。您需要有关该主题的视频,因此请先从视频开始,而不是主题。 :)
编辑:第二个功能的缺点是它将预加载所有数据,它可能会更短,但在服务器上更重。除非我需要知道主题和章节,否则我会使用第一个。