MySQL & PHP - Создание множественных родительских и дочерних отношений - PullRequest
9 голосов
/ 25 марта 2010

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

id (int) - Primary key
name (varchar) - Name of the Category
parentid (int) - Parent ID of this Category referenced to same table (Self Join)

Но суть в том, что я требую, чтобы категория была дочерней по отношению к нескольким родительским категориям ... Так же, как отношение "Имеет и принадлежит многим" (HABTM).

Я знаю, что если есть две таблицы, категории и элементы, мы используем объединяющую таблицу category_items, чтобы перечислить отношения HABTM. Но здесь у меня не две таблицы, а только таблица, но я должен как-то показать отношения HABTM к себе. Возможно ли это с помощью одной таблицы? Если да, то как? Если это невозможно, каким правилам (именам таблиц, полям) следует следовать при создании дополнительной таблицы объединения?

Я пытаюсь добиться этого с помощью CakePHP. Если кто-то может предложить решение CakePHP для этой проблемы, это было бы здорово. Даже если это невозможно, приветствуется любое решение о создании таблицы соединений. Спасибо за ваше время.

- Правка - Мой вопрос кажется немного запутанным, поэтому я пытаюсь переформулировать то, что я ищу. В традиционных самозависимых (самосоединяющихся) родительско-дочерних отношениях каждый элемент может иметь только одного родителя. То, что я ищу, - это симуляция отношения HABTM, то есть нескольких родителей для каждого элемента.

Категории и элементы - для определения HABTM мы используем таблицу соединений category_items.

Если в категориях мне нужен HABTM, что мне делать?

Ответы [ 6 ]

3 голосов
/ 25 марта 2010

Надеюсь, неплохо будет ответить второй раз, неправильно поняв вопрос в первый раз. Ниже приведена реализация 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'
        )
    );
}
2 голосов
/ 25 марта 2010

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

Именно то, что вы хотите в себе ГДЕ и ваш SELECT будет соответствовать тому, чего вы надеетесь достичь. Относительно того, хотите ли вы LEFT OUTER JOIN или INNER JOIN , это зависит от того, хотите ли вы возвращать категории в m. *, У которых нет записи в вашей таблице отношениях (= не есть любой родитель). Если вы новичок в присоединении к синтаксису, ознакомьтесь с этой статьей вики о присоединениях .

1 голос
/ 25 марта 2010

Это почти точно то, для чего предназначено поведение Tree . Поведение построено поверх MPTT (модифицированный обход дерева предзаказа) . Вы бы настроили его так:

Добавьте следующие поля в вашу таблицу:

`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 <select> в формы изменения категории, а поведение Tree позаботится обо всем остальном. Я полагаю, что вы могли бы вручную переупорядочить категории в пределах уровня иерархии категорий, но вам, вероятно, лучше использовать методы moveUp и moveDown, доступные в моделях, расширенных с помощью поведения дерева.

Здесь также полезен Помощник по дереву для преобразования списков деревьев в упорядоченные / неупорядоченные списки в ваших представлениях.

0 голосов
/ 24 февраля 2011

Вы можете использовать рекурсию для построения родительского / дочернего неограниченного дерева. Более подробную информацию можно найти по следующему адресу. Получить неограниченное родительское и дочернее дерево в php

0 голосов
/ 29 марта 2010

Наконец-то.

Таблица 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' => ''
        )
    );
}
?>

Я сгенерировал Controller и Views, используя оболочку Cake Bake.Сейчас работает нормально.Спасибо за все ваши идеи, они очень мне помогли.

0 голосов
/ 25 марта 2010

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

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

items
categories
categories_items

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

category_id
item_id

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...