Я пытаюсь создать таблицу категорий использования системы навигации с иерархиями. Обычно, таблица была бы определена следующим образом:
id (int) - Primary key
name (varchar) - Name of the Category
parentid (int) - Parent ID of this Category referenced to same table (Self Join)
Но выгода - то, что я требую, чтобы категория могла быть ребенком к нескольким родительским категориям.. Точно так же, как отношение Имеет и принадлежит многим (HABTM).
Я знаю, что, если существует две таблицы, категории и объекты, мы используем объединяющую таблицу categories_items для списка отношений HABTM. Но здесь я не имею двух таблиц, но только таблицы, но должен так или иначе показать отношения HABTM к себе. Это быть возможным использованием единственной таблицы? Если да, Как? Если не возможный, за какими правилами (именование таблицы, поля) я должен следовать при создании дополнительной объединяющей таблицы?
Я пытаюсь достигнуть этого использования CakePHP, Если бы кто-то может предоставить решение CakePHP для этой проблемы, которая была бы потрясающей. Даже если это не возможно, любое решение о создании объединяющей таблицы ценится. Спасибо за внимание.
- Редактирование - Мой вопрос, кажется, немного сбивает с толку, таким образом, я пытаюсь вновь заявить о том, что я ищу. В традиционном сам ссылаемый (сам соединение) родительско-дочерние отношения, каждый объект может иметь только одного родителя. То, что я ищу, должно моделировать отношение HABTM т.е. несколько родителей для каждого объекта.
Категории и Объекты - Для определения HABTM мы используем categories_items объединяющую таблицу.
Если в Категориях мне нужен HABTM, что я должен сделать?
Наконец-то понял.
Таблица Naviitems:
CREATE TABLE IF NOT EXISTS `naviitems` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`linkurl` varchar(250) NOT NULL,
PRIMARY KEY (`id`)
);
Таблица самостоятельного соединения:
CREATE TABLE IF NOT EXISTS `naviitems_parents` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`naviitem_id` int(11) NOT NULL,
`parent_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
);
Модель Naviitems:
<?php
class Naviitem extends AppModel {
var $name = 'Naviitem';
//The Associations below have been created with all possible keys, those that are not needed can be removed
var $hasAndBelongsToMany = array(
'Parent' => array(
'className' => 'Naviitem',
'joinTable' => 'naviitems_parents',
'foreignKey' => 'naviitem_id',
'associationForeignKey' => 'parent_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
)
);
}
?>
Я сгенерировал контроллер и представления, используя оболочку Cake Bake. Теперь все работает нормально. Спасибо за все идеи, которые вы внесли, они мне очень помогли.
Попытка втиснуть отношение n: m (HABTM) в отношение 1: n - не лучшая практика, и вы столкнетесь с ограничениями, которые не могли бы есть, если вы сделали это чисто, но вот как вы могли бы это сделать (общий PHP, а не специально для CakePHP):
Вы можете создать столбец в своей таблице для хранения всех родительских идентификаторов в списке, разделенном запятыми. Вы можете прочитать отдельные идентификаторы, используя ...
$ids = explode(',', $idsFromColumn);
... и записать их обратно в столбец, используя ...
$idsForColumn = implode(',', $ids);
Фактическое чтение-запись базы данных будет происходить до / после этих фрагментов, соответственно.
Если вы хотите сделать это правильно, вы хотите, чтобы ваша основная таблица выглядела так:
id (int) - Primary key
name (varchar) - Name of the Category
А ваша таблица отношений n: m выглядела так:
id (int) - child
parentid (int) - parent
Вы бы запросили ее так:
SELECT ...
FROM
main_table AS m
[LEFT OUTER|INNER] JOIN
relationship_table AS r
ON r.id=m.id
[LEFT OUTER|INNER] JOIN
main_table AS n
ON r.parentid=n.id
WHERE ...
Точно то, что вы хотите от себя WHERE и ваш SELECT , будет соответствовать тому, чего вы надеетесь достичь. Что касается того, хотите ли вы LEFT OUTER JOIN или INNER JOIN ), это зависит от того, хотите ли вы вернуть категории в m. *, Для которых нет записи в вашей таблице отношений (= не есть родитель). Если вы новичок в синтаксисе объединения, ознакомьтесь с этой статьей Wiki о объединениях .
То, чего вы пытаетесь достичь, на самом деле не является Подход торт способом. Вы должны использовать две таблицы с таблицей соединения между ними. Изречение Cake - «соглашение важнее конфигурации», поэтому вам действительно следует использовать стандартный способ приготовления пирога.
Чтобы создать HABTM, вам понадобятся три таблицы.
items
categories
categories_items
Предмет и категория соответствуют вашим ожиданиям. Ваша объединяемая таблица должна содержать только два идентификатора соединенных таблиц, как показано ниже
category_id
item_id
. Это позволит вам отображать один элемент навигации в нескольких категориях, если вы захотите.
Дополнительную информацию можно найти в книге http://book.cakephp.org/view/1044/hasAndBelongsToMany-HABTM
Надеюсь, это неплохой тон, чтобы ответить во второй раз, если вы неправильно поняли вопрос в первый раз. Следующее - это, по сути, реализация CakePHP ответа pinkgothic .
Новая таблица соединения HABTM:
CREATE TABLE `categories_parent_categories` (
`category_id` int(10) unsigned NOT NULL,
`parent_category_id` int(10) unsigned default NULL,
`order` int(10) unsigned NOT NULL default '0'
);
Связь в модели:
class Category extends AppModel
{
var $hasAndBelongsToMany = array(
'ParentCategory' => array(
'className' => 'Category',
'joinTable' => 'categories_parent_categories',
'foreignKey' => 'category_id',
'associationForeignKey' => 'parent_category_id',
'order' => 'CategoriesParentCategory.order'
)
);
}
Это почти именно то, для чего предназначено поведение дерева . Поведение построено на основе MPTT (Modified Preorder Tree Traversal) . Вы должны сконфигурировать его так:
Добавьте следующие поля в вашу таблицу:
`parent_id` int(10) unsigned default NULL
`lft` int(10) unsigned default NULL
`rght` int(10) unsigned default NULL
Модель:
class Category extends AppModel
{
var $actsAs = array('Tree');
}
Затем вы встроите parent_id
в формы модификации категорий, а Об остальном позаботится поведение дерева. Я полагаю, вы могли бы вручную обрабатывать переупорядочение категорий внутри уровня иерархии категорий, но вам, вероятно, лучше использовать методы moveUp
и moveDown
, доступные в моделях, расширенных с помощью Tree поведение.
Здесь также есть полезный Tree Helper для преобразования древовидных списков в упорядоченные / неупорядоченные списки в ваших представлениях.