1

我已经使用 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();
    }
}

上面的代码效率不高,因为它进行了太多查询。

我考虑过使用joindatabase query builder,但它们都没有返回模型对象作为结果。我也研究了with(),但它似乎只适用于一对一的关系。

在 ORM 对象上使用 join 返回一个 OPM 对象,但它不返回连接表中的数据。

我在这里最好的选择是什么?我想最小化查询数,也想得到 ORM 对象的结果。不管是什么,都应该返回教程、章节和视频中的所有列。

4

2 回答 2

3

首先,您的代码过多。ORM 方法 find() 返回 1 个 Model_Subject 对象。看

$chapters = ORM::factory('subject', 1)->chapters->find_all();
foreach($chapters as $chapter) 
{
    $videos = $chapter->videos->find_all();
}

使用 DB builder,您只能发出 2 个请求。首先获取所有章节 ID 的数组:

$chapters = DB::select('id')
   ->from('chapters')
   ->where('subject_id', '=', '1')
   ->execute()
   ->as_array(NULL, 'id');

第二 - 通过 ids 获取所有视频作为 Model_Video 对象

$videos = DB::select('id')
    ->from('videos')
    ->where('chapter_id', 'IN', $chapters)
    ->as_object('Model_Video') 
    ->execute()
    ->as_array();
于 2013-11-18T16:01:44.457 回答
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();

像这样的事情通常有助于“向后”思考。您需要有关该主题的视频,因此请从视频而不是主题开始。:)

编辑:第二个函数的缺点是它会预加载所有数据,写起来可能更短,但在服务器上更重。除非我无论如何都需要知道主题和章节,否则我会使用第一个。

于 2013-11-22T14:11:53.770 回答