После довольно продолжительного перерыва продолжаем знакомиться со связями между таблицами и работой с ними посредством ORM. И разберем мы оставшиеся две связи — «один-ко-многим» и «многие ко многим».
Один ко многим
Как и в прошлом примере у нас будет две таблицы — список книг и список авторов. Поскольку мы договорились, что одна книга может иметь только одного автора, то таблицы будут такими:
А модели вот такими:
Class Model_Author extends ORM { protected $_has_many = array( 'books' => array( 'model' => 'book', 'foreign_key' => 'author_id', ) ); };
class Model_Book extends ORM { }
Если сравнить этот пример с предыдущим, можно увидеть, что массив с параметрами переместился в класс, описывающий авторов и стал называться $_has_many (есть много). И получение записей из связанной таблицы теперь происходит по другому.
$author = ORM::factory('author', 1); $books = $author->books->find_all(); foreach($books as $book) { echo $book->id .' - '. $book->name .'<br />'; }
Получаем результат:
1 - Саргассы в космосе 3 - Разум на торги
Запросы, которые создаются при этом, выглядят следующим образом:
SELECT `author`.* FROM `authors` AS `author` WHERE `author`.`id` = 1 LIMIT 1 SELECT `book`.* FROM `books` AS `book` WHERE `book`.`author_id` = '1'
Многие ко многим
В качестве примера берем фильмы и жанры. Для реализации этой связи нам понадобится промежуточная таблица.
Модели выглядят почти также, как в предыдущем примере (связь один-ко-многим), только вместо внешнего ключа foreign_key мы указываем нашу промежуточную таблицы.
class Model_Film extends ORM { protected $_has_many = array( 'genre' => array( 'model' => 'genre', 'through' => 'genre_films', ) ); }
class Model_Genre extends ORM { protected $_table_name = 'genre'; protected $_has_many = array( 'films' => array( 'model' => 'film', 'through' => 'genre_films', ), ); }
Теперь получать данные сразу из таблиц жанров и фильмов можно так:
$genre = ORM::factory('genre', 2); $films = $genre->films->find_all(); foreach($films as $film) { echo $genre->name .' - '. $film->name .'<br />'; }
Или так:
$film = ORM::factory('film', 3); $genre_f = $film->genre->find_all(); foreach($genre_f as $genre) { echo $genre->name .' - '. $film->name .'<br />'; }
Результат:
Фантастика - Вспомнить все Фантастика - Прометей Комедия - 8 первых свиданий Мелодрама - 8 первых свиданий
Запросы:
SELECT `genre`.* FROM `genre` AS `genre` WHERE `genre`.`id` = 2 LIMIT 1 SELECT `film`.* FROM `films` AS `film` JOIN `genre_films` ON (`genre_films`.`film_id` = `film`.`id`) WHERE `genre_films`.`genre_id` = '2' SELECT `film`.* FROM `films` AS `film` WHERE `film`.`id` = 3 LIMIT 1 SELECT `genre`.* FROM `genre` AS `genre` JOIN `genre_films` ON (`genre_films`.`genre_id` = `genre`.`id`) WHERE `genre_films`.`film_id` = '3'
Вот и все, со связями покончено. Пользуйтесь, это действительно очень удобно.
Пожалуйста, зарегистрируйтесь для комментирования.
А подскажите, пожалуйста, можно ли использовать ORM если мне нужна связь между тремя таблицами с таким запросов SELECT customers.name FROM customers, orders, books WHERE customers.customerid = orders.custormerid AND orders.id=books.isbn
Одну таблицу связать со второй, а вторую с третьей. Все в моделях прописывается.
Что-то давно обновлений и дополнений не было, пичаль…
Не то слово
Просто я сейчас занят проектом, который уже приносит реальные деньги. Да и уезжаю скоро, не до всего этого. Вот приеду весной, а там посмотрим. Уверен, что уроки еще будут
Уже скоро зима, а новых материалов по прежнему нету ;(
Очень надеюсь что Вы не забросили проект, так как он реально полезных и помогает разобраться.
Вопрос в связях, никак не могу разобраться
Делаю мультиязычность. Структура таблиц такая:
Photogalleries[id, url]
Phototext[id, photo_id, description, lang]
В модели Photo сделал связь:
protected $_has_many = array(
‘phototext’ => array(
‘model’ => ‘phototext’,
‘foreign_key’ => ‘photo_id’,
),
);
Как сделать выборку изображений только с текущим языком (ну например lang=’ru’)?
А как правильно через ORM сохранить данные в промежуточную таблицу?
http://blogocms.ru/2011/01/kohana-3-0-shpargalka-po-orm/ вот этой информации, о методе add, тут явно не хватает