MySQL & PHP - Создание нескольких родительских дочерних отношений

Я пытаюсь создать таблицу категорий использования системы навигации с иерархиями. Обычно, таблица была бы определена следующим образом:

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, что я должен сделать?

9
задан Ashok 25 March 2010 в 03:26
поделиться

5 ответов

Наконец-то понял.

Таблица 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. Теперь все работает нормально. Спасибо за все идеи, которые вы внесли, они мне очень помогли.

0
ответ дан 3 November 2019 в 07:13
поделиться

Попытка втиснуть отношение 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 о объединениях .

2
ответ дан 3 November 2019 в 07:13
поделиться

То, чего вы пытаетесь достичь, на самом деле не является Подход торт способом. Вы должны использовать две таблицы с таблицей соединения между ними. Изречение Cake - «соглашение важнее конфигурации», поэтому вам действительно следует использовать стандартный способ приготовления пирога.

Чтобы создать HABTM, вам понадобятся три таблицы.

items
categories
categories_items

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

category_id
item_id

. Это позволит вам отображать один элемент навигации в нескольких категориях, если вы захотите.

Дополнительную информацию можно найти в книге http://book.cakephp.org/view/1044/hasAndBelongsToMany-HABTM

0
ответ дан 3 November 2019 в 07:13
поделиться

Надеюсь, это неплохой тон, чтобы ответить во второй раз, если вы неправильно поняли вопрос в первый раз. Следующее - это, по сути, реализация 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'
        )
    );
}
3
ответ дан 3 November 2019 в 07:13
поделиться

Это почти именно то, для чего предназначено поведение дерева . Поведение построено на основе 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