Linked-связи Active Record

Данный раздел рассказывает про метод linked() и его псевдоним _*.

Вызывается метод так:

d()->User->_groups;
//или
d()->User->linked('groups');

Метод, применённый к списку (объекту ActiveRecord) возвращает все объекты, которые связаны названием столбца с каждым из элементов текущего списка, будь то дочерние элементы или родительские.

Для объекта, содержащего список элементов, метод linked, который ищет дочерние элементы, вернёт список всех дочерних элементов для каждого объекта в текущем списке.

Для объекта, содержащего список элементов, метод linked, который ищет родительские элементы, вернёт список всех родительских элементов для каждого объекта в текущем списке.

Метод linked всегда возвращает объект ActiveRecord. В случае, когда связей не найдено, возвращается пустая строка.

В этом плане метод схож с объектом jQuery, который всегда возвращает массив (даже если элемент один), и работает тоже с массивом.

В данном случае массивом всегда служит объект ActiveRecord, который привязан к списку объектов. К нему по прежнему можно применять фильтрацию, сортировку и т.д.

Для получения связей используется название столбца.

  • Для дочерних элементов d()->Catalog->_products будет искать таблицу products со столбцом catalog_id.
  • Для родительских элементов d()->Product->_catalogs будет искать таблицу catalogs и столбец catalog_id в текущей таблице.

Приоритетом (когда можно найти и то и то) является список дочерних элементов.

Ниже представлены примеры использования этого метода, расположенные по порядку увеличения сложности примеров.

Уровень 1

Уровень первый - разминка. Мы можем получать данные из связанных таблиц.

Пример первый - каталоги товаров

Мы имеем таблицы products и catalogs - каталоги и товары. Каждый товар может быть в каком-либо каталоге. Каталоги имеют структуру - один каталог может включать в себя несколько подкаталогов.

связь первая

Получить все товары каталога с ID=4:

d()->prod_list = d()->Catalog(4)->_products;

Далее мы можем выводить товары как обычно:

<foreach prod_list>
    <p>{.title}: {.cost} рублей.</p>
</foreach>

Даже если linked возвращает массив, следует помнить, что любой объект ActiveRecord - тоже массив, пусть и из одного элемента.

Вывести название каталога для товара с ID=3:

d()->Product(3)->_catalogs->title;

Получить каталог самого дорогого товара:

d()->Product->order_by('cost desc')->limit(1)->_catalogs;

Получить все подкаталоги каталога c ID=4:

d()->Catalog(4)->_catalogs;

Получить все товары каталога с ID=4, которые стоят больше 100 рублей:

d()->Catalog(4)->_products->where('cost > 100');

TODO: Полиморф

Есть таблица users у каждого пользователя есть отец (father_id). В таблице fathers есть столбец user_id, указывающий на пользователя. Вывести отца пользователя с ID=4:

d()->User(4)->_fathers->_users;
//Альтернатива:
d()->User(4)->father->user;

Уровень 2

В данной группе примеров рассматриваются задачи, когда мы обращаемся не к одному элементу, а к группе: товаров или каталогов, пользователей или документов. При этом синтаксис остаётся тем же.

Пример тот же. Данные те же. Условия усложнены:

Получить все подкаталоги каталога с ID=4:

d()->Catalog(4)->_catalogs;

Получить все подкаталоги каталогов с ID=4 и ID=5:

d()->Catalog(array(4,5))->_catalogs;

Получить все товары всех подкаталогов каталога c ID=4:

d()->Catalog(4)->_catalogs->_products;

Получить все товары всех подкаталогов каталога c ID=4, 5 и 6:

d()->Catalog(array(4,5,6))->_catalogs->_products;

Получить все товары всех каталогов, отмеченных как новые is_new = 1:

d()->Catalog->where('is_new = 1')->_products;

Получить все каталоги тех товаров, которые стоят больше 100 рублей:

d()->Product->where('cost > 100')->_catalogs;

Пример второй - клиенты и города

Мы имеем список клиентов, каждый из которых имеет указанный город из таблицы cities.

связь вторая

Получить все города, которые имеются в данном списке клиентов. Список клиентов ищется по полю name, которое должно включать ключевые слова (поиск).

d()->Client->search('name', $_GET['s'])->_cities;

Пользователь выбрал (например, галочками) интересующие его города. Получить всех клиентов, которые имеются в массиве городов

// URL страницы выглядит так:
// http://site/clients/?cities_list[]=3&cities_list[]=34&cities_list[]=37&cities_list[]=71
d()->City($_GET['cities_list'])->_clients;

Пример третий - товары и бренды.

Есть таблица брендов. У каждого товара есть указанный бренд (производитель).

связь третья

Получить список всех товаров каталога с ID=3. Над списком товаров вывести список брендов, которые присутствуют в данном списке:

d()->products = d()->Catalog(3)->_products;
d()->brands = d()->products->_brands;

Получить список всех товаров каталога с ID=3 и брендом с ID=7. Над списком товаров вывести список брендов, которые присутствуют в каталоге:

d()->products = d()->Catalog(3)->_products->where('brand_id = ?', 7);
d()->brands=d()->Catalog(3)->_products->_brands;

Получить список каталогов, в которых есть товары с брендом "Apple":

d()->Brand->where('title = ?', "Apple")->_products->_catalogs;

Получить список всех брендов, которые присутствуют во всех каталогах:

d()->Catalog->_products->_brands;

Пример четвёртый: сотрудники и их фотографии

У нас есть таблица с клиентами. У каждого клиента есть город, у каждого города есть регион. У клиента есть несколько сотрудников (employees). У сотрудника есть несколько фотографий. Каждая фотография может иметь несколько тегов (пометок).

пример четвёртый

Вывести все теги фотографий тех сотрудников фирм, которые работают в региона с ID=3;

d()->Region(3)->_cities->_clients->_employees->_photos->_tags; 

Пример пятый: сотрудники, их города и фотографии

У нас есть таблица с клиентами (companies). У каждого клиента есть ряд сотрудников (employees), каждому из которых можно указать город и привязать несколько фотографий. У каждого клиента есть пользователь - автор (user).

пример пятый

Вывести все фотографии сотрудников из региона с ID=4:

d()->Region(4)->_cities->_employees->_photos;

Вывести список пользователей, которые управляют клиентами, сотрудники которых из городов региона с ID=4:

d()->Region(4)->_cities->_employees->_clients->_users;

TODO: Полиморф

Есть таблица users у каждого пользователя есть отец (father_id). В таблице fathers есть столбец user_id, указывающий на пользователя. Вывести детей пользователя с ID=4:

d()->User(4)->_fathers->_users;//Шозана?

Уровень 3

Примеры этого раздела используют связь many-to-many, когда товар может быть привязан к нескольким категориям, у объявления несколько авторов, несколько пользователей в одной группе. В предыдущих примерах были неявные примеры использования many-to-many.

Документы пользователи права запись и чтение

Документы пользователи права запись и чтение в отдельной таблоице в том числе кто добавил

Документы пользователи права запись и чтение в отдельной таблоице в том числе кто добавил история изменения доступов, некотрые кативны некоторые нет

TODO: Полиморфы

У нас есть таблица товаров products. Есть рекомендуемые аксессуары, которые тоже находятся в таблице products. Есть таблица accessories_to_products. В каждой строке таблицы аксессуаров есть строка product_id, указывающая на товар. Получить список аксессуаров товара c ID=4:

d()->Good(4)->_accessories_to_goods->_accessories->_goods;

many_to_many, many-to-many to many-to-many.

Уровень 4

Плюс. Типы прав (админ и т.д.)

Уровень 5

Несколько строк

Документ в нескольких разделах одновременно. Вывести документы раздела, к которым есть доступ (группы, права).

"Пользователь может состоять в одной или нескольких группах, группа может иметь доступы разного уровня к одному или несколкьим документами, пользователь может иметь уровень разного доступа к одному или нескольким документами пользователь может быть администратором группы", показать все документы к которым имеет доступ пользователь, включая его документы и документы всех пользователей, всех групп, админом которых он является, с определенным уровнем доступа

Уровень X

Товары и каталоги. Всё находится в одной таблице (каталог можно купить).

Друзьяшки!

Список похожих товаров.

Список аксессуаров (привязан к каталогу и товару). И обратно - получить список товаров, для которого товар - аксессуар.

Список партнёров/торговых точек/компаний в группе компаний.

И обратно - получить родительскую компанию.

Вывести регион, в котором менеджеры меньше всего заполняют теги фотографий сотрудников.

Таск менеджер. Таски могут иметь большую вложенность, ограниченную только конфигом. У каждого таска есть автор, есть ответственные за выполнение которые могут менять статус. У каждого юзера есть руководитель кроме генерального. Каждый руководитель должен видеть таски подчиненных, и, опционально, всех подчиненных его подчиненных и т.п. структура компании тоже может быть сильно вложенной еще есть юзеры-партнеры которые вне иерархии, а аткже у тасков могут быть наблюдатели вообще любые


comments powered by Disqus