2013-11-18 3 views
0

Я использую Kohana в течение нескольких недель. Одна вещь, которую я заметил, это то, что Кохане не хватает загруженной загрузки (насколько я знаю). Скажем, у меня есть следующие таблицы.Как запросить это с помощью ORM?

Предметы

id 
name 

Главы

id 
subject_id 
name 

Видео

id 
chapter_id 
name 

Когда пользователь открывает су bject, я хочу отобразить все главы и видео. С 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(); 
    } 
} 

Приведенный выше код неэффективен, так как он вызывает слишком много запросов.

Я думал об использовании присоединиться или базы данных построитель запросов, но оба они не возвращают объект модели, как и их результаты. Я также изучил с(), но похоже, что он работает только с отношениями «один к одному».

Использование объединения объекта ORM возвращает объект OPM, но он не возвращает данные из таблиц соединения.

Какой был бы мой лучший вариант здесь? Я хотел бы свести к минимуму количество запросов, а также получить объекты ORM в результате. Как бы то ни было, нужно вернуть все столбцы из учебников, глав и видео.

+0

Вы видели [Kohana_Database_Query_Builder :: as_object()] (http://kohanaframework.org/3.3/guide-api/Kohana_Database_Query_Builder # as_object)? – Darsstar

+0

@Darsstar // проблема as_object заключается в том, что он принимает только одно имя класса. Что делать, если у меня есть запрос, который возвращает данные из нескольких таблиц, присоединяя их? Это главная проблема, с которой я сталкиваюсь. – Moon

+0

Прошло много времени с тех пор, как я работал с ORM. Но кажется, что двоеточие (':') имеет особое значение в именах выбранных столбцов: http://kohanaframework.org/3.3/guide-api/ORM#_load_values ​​ – Darsstar

ответ

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 запроса. Во-первых получить массив из всех глав идентификаторов:

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

Второй - получить все видео идентификаторов как объект Model_Video

$videos = DB::select('id') 
    ->from('videos') 
    ->where('chapter_id', 'IN', $chapters) 
    ->as_object('Model_Video') 
    ->execute() 
    ->as_array(); 
+0

Я не думаю, что вы поняли мою точку зрения. Я знаю, что вы можете использовать построитель запросов БД или DB :: select. Проблема DB :: select или построителя запросов БД заключается в том, что они не возвращают объект ORM, что невозможно вызвать метод в объекте. – Moon

+0

Вы пытаетесь выполнить этот код, а не печатать переменную $ videos? as_object ('Model_Video') означает, что построитель запросов возвращает объект ORM –

+0

Хорошо ... Я думаю, что теперь я понимаю ваш код. Здесь есть две проблемы. Я не хочу запускать два запроса, когда могу это сделать с одним. Во-вторых, мне все равно нужно связать каждое видео с главами. Тем не менее, я думаю, что это лучший ответ, который я нашел до сих пор. Спасибо. – Moon

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(); 

с вещами, как это часто помогает думать «назад». Вам нужны видео на эту тему, поэтому начните с видео вместо темы. :)

EDIT: Недостатком второй функции является то, что она будет предварительно загружать все данные, она может быть короче для записи, но более тяжелая на сервере. Я бы использовал первый, если мне вообще не нужно знать тему и главу.

Смежные вопросы