Администрирование множественных связей между таблицами (multilink / relations)

Для организации множественных связей между материалами Нодуса есть решение. Но и без нодуса ТАО позволяют организовать множественную связь между материалами.

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

Алгоритм организации множественной связи (multilink)

1. В описание таблицы новостей добавляем новое поле (тип новости).Указываем ему тип multilink, а в items указываем источник данных orm. Описывать sqltype не надо.

// News/config/fields.php
return array(
	'news' => array(
		...
		'type' => array(
			'type' => 'multilink',
			'items' => 'orm:news_types',
			'caption' => 'Тип',
			'tab' => 'common',
		),
	),
);

2. Для хранения связей создаем таблицу с произвольным именем.

//  News/config/fields.php
...
'news_types_ties' => array(
	'new_id' => array(
		'sqltype' => 'int index',
	),
	'type' => array(
		'sqltype' => 'int index',
	),
),
...
  • new_id - поле имеет произвольное название. Здесь будет храниться id новости.
  • type - имя поля должно совпадать с именем ранее созданного поля multilink.

3. Для таблицы связей необходимо создать маппер.

// News/lib/Mapper.php

class Component_News_Mapper_Ties extends CMS_ORM_Mapper implements Core_ModuleInterface
{
	public function setup()
	{
		return parent::setup()
			->table('news_types_ties')
			->classname('CMS.ORM.Entity');
	}

}

Зарегистрировать его в конфигурационных настройках компонента.

// News/config/component.php

return array(
	'orm' => array(
		...
		'news_types_ties' => 'Component.News.Mapper.Ties',
	),
...
);

4. В описании сущности (Entity), для которой добавлялось поле multilink, укажем маппер таблицы связей. Для этого необходимо воспользоваться методом multilinks().

// News/lib/Mapper.php

class Component_News_New extends CMS_ORM_Entity implements Core_ModuleInterface
{
	...
	protected function multilinks()
	{
		return array('news_types_ties');
	}
}

Никакой дополнительной организации методов записи или удаления данных не требуется.

Организация множественной связи между материалами (relations)

Множественную связь можно реализовать еще проще, используя тип поля relations.

При добавлении нового поля (тип новости), указываем ему тип relations (также без описания sqltype), а в items указываем источник данных orm или массив в формате CMS::items_for_select.

// News/config/fields.php
return array(
	'news' => array(
		...
		'type' => array(
			'type' => 'relations',
			'items' => 'orm:news_types',
			'caption' => 'Тип',
			'tab' => 'common',
		),
	),
);

Больше ничего не требуется. Здесь связь между материалами осуществляется также через стороннюю таблицу связей. Только в этом случае, таблица связей создается автоматически (NameTable_NameField_relations) с полями item_id, rel_id.

В случае, если требуется создать таблицу или поля (или и то и другое) со своими именами, то для этого можно воспользоваться свойствами table_name, item_id_name, rel_id_name. В которых указать имена таблицы и полей. Свойства описываются в том же поле.

// News/config/fields.php
return array(
	'news' => array(
		...
		'type' => array(
			'type' => 'relations',
			'table_name' => 'other_table_rel',
			'item_id_name' => 'new_id',
			'rel_id_name' =>'type_id',
			'items' => 'orm:news_types',
			...
		),
	),
);

Данный тип имеет ряд ограничений:

  • подходит преимущественно для небольших списков, т.к. нет средств для управления и поиска по очень большому списку.
  • реализация типа построена на прямых MySQL-запросах в базу. Т.е., если БД реализована не на MySQL, то воспользоваться данным типом поля не получится, оно не будет работать.
Метки: ORM
16.07.2014
Все статьи