Основы ORM — связи — Часть 2

Комментарии: 8  Просмотры: 22 736

После довольно продолжительного перерыва продолжаем знакомиться со связями между таблицами и работой с ними посредством ORM. И разберем мы оставшиеся две связи — «один-ко-многим» и «многие ко многим».

Один ко многим
Как и в прошлом примере у нас будет две таблицы — список книг и список авторов. Поскольку мы договорились, что одна книга может иметь только одного автора, то таблицы будут такими:
ORM Связь один ко многим в Kohana

А модели вот такими:

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'

Многие ко многим
В качестве примера берем фильмы и жанры. Для реализации этой связи нам понадобится промежуточная таблица.
ORM Связь многие ко многим в Kohana

Модели выглядят почти также, как в предыдущем примере (связь один-ко-многим), только вместо внешнего ключа 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'

Вот и все, со связями покончено. Пользуйтесь, это действительно очень удобно.

<< Назад | Обсудить на форуме


К записи оставлено 8 коммент.

А подскажите, пожалуйста, можно ли использовать 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, тут явно не хватает



Оставить комментарий или два

Пожалуйста, зарегистрируйтесь для комментирования.