2009-07-24 10 views
3

Mit nur ein bisschen Erfahrung mit Datenbanken und keine formale Ausbildung mit ihnen, bin ich ein bisschen fest, wie dies zu modellieren (und die Daten, die ich davon in PHP abrufen). Dies ist, was ich versuche zu modellieren:Wie modelliert man eine Viele-zu-Viele-Beziehung?

Für jedes Element auf meiner Website, ist es erlaubt, mehrere Tags wie Datei, Upload, PHP, rekursiv usw. haben. Allerdings sind die Tags wiederverwendbar, ich kann zwei verschiedene haben Elemente und sie könnten jeweils das PHP-Tag haben.

Ich habe versucht, darüber nachzulesen, wie man das macht und ob es Mangel an Erfahrung damit oder etwas anderes ist, weiß ich nicht, aber ich kann nicht scheinen, das Konzept zu begreifen. Anscheinend brauchst du einen mittleren Tisch, der die beiden miteinander verbindet?

Auch wenn ich diese Beziehung und die Tabellen definiert, wie würde ich Dinge tun, wie zum Beispiel: - Rufen Sie alle Einzelteile mit einem bestimmten Tag? - Abrufen aller Tags, die ein Element hat?

Vielen Dank für Ihre Hilfe, auch wenn jemand weitere Informationen zu diesem Thema auflisten könnte, um mein Verständnis des Konzepts zu vertiefen, das großartig wäre.

Antwort

7

Der db-Teil ist einfach. Dies ist nur ein Beispiel, damit Sie sehen können, wie db aussehen kann, nicht irgendwelche bestimmten SQL-Engine-Abfragen.

CREATE TABLE posts (
    id INT PRIMARY KEY, 
    subject VARCHAR(100), 
    body TEXT 
) 

CREATE TABLE tags (
    id INT PRIMARY KEY, 
    name VARCHAR(50) 
) 

CREATE TABLE post_tags (
    post_id INT, 
    tag_id INT, 
    FOREIGN KEY (post_id) REFERENCES posts (id), 
    FOREIGN KEY (tag_id) REFERENCES posts (id) 
) 

Um Elemente mit yourTag Tag erhalten Sie nur Abfrage wie diese

SELECT P.* 
FROM posts P 
    LEFT JOIN post_tags PT ON (PT.post_id = P.id) 
    LEFT JOIN tags T ON (T.id = PT.tag_id) 
WHERE T.name = 'yourTag'; 

laufen Schlüssel Post mit id von 123 Sie diese Abfrage ausführen verbunden zu bekommen:

SELECT T.* 
FROM tags T 
    LEFT JOIN post_tags PT ON (T.id = PT.tag_id) 
    LEFT JOIN posts P ON (PT.post_id = P.id) 
WHERE P.id = 123; 

Für Im PHP-Teil könnte man ein Framework verwenden. Viele (wenn nicht alle) Frameworks können solche Beziehungen leicht modellieren. Zum Beispiel in CakePHP dies so getan:

class Post extends AppModel { 
    $useTable = 'posts'; 
    $hasAndBelongsToMany = array(
     'Tag' => array(
      'className' => 'Tag' 
      'joinTable' => 'post_tags' 
      'foreignKey' => 'post_id' 
      'associationForeignKey' => 'tag_id' 
     ) 
    ); 
} 

class Tag extends AppModel { 
    $useTable = 'tags'; 
    $hasAndBelongsToMany = array(
     'Post' => array(
      'className' => 'Post' 
      'joinTable' => 'post_tags' 
      'foreignKey' => 'tag_id' 
      'associationForeignKey' => 'post_id' 
     ) 
    ); 
} 
+0

ITYM Tag -> $ hasAndBelongsToMany = array ('Post' ... etc. – Stobor

+0

Danke für die Datenbank Teil das ist fantastisch. Ich benutze CodeIgniter und modelliert solche Beziehungen nicht wirklich, man muss es selbst machen. Außerdem würde ich lieber die SQL-Abfragen verstehen, als wenn man sich auf Automagic verlässt. – Zim

+0

@Stobor - Danke, dass Sie das gefunden haben, das war ein Kopierfehler – RaYell

0

Du hast Recht, many-to-many-Beziehungen werden durch zusätzliche Tabelle implementiert, zum Beispiel:

Blog_entry(entry_id, entry_body) 
Tag(tag_id, tag_name) 
Entry_tag(entry_id, tag_id) 

Alle Operationen durchgeführt werden mehrere mit verbindet. Zum Beispiel, wenn Sie alle Einträge mit dem Tag ‚foo‘ auswählen möchten, mit Hilfe von Tabellen aus meinem Beispiel, müssen Sie ausführen:

select * 
from 
    blog_entry, tag, entry_tag 
where 
    tag.tag_name = 'foo' and 
    entry_tag.tag_id = tag.tag_id and 
    entry_tag.entry_id = blog_entry.entry_id 

(Update) Zum Abrufen alle Schlüsselpaare, bestimmten Eintrag (hier mit der ID 123) hat:

0

Ja, viele-zu-viele-Beziehung benötigt zusätzliche, dritte Tabelle, genannt Assoziationstabelle.

Database Teil ist nicht so schwer, es schwieriger ist es mit allen jenen links in Code zu verwenden, schließt sich und es kann ziemlich chaotisch :)

Mein Rat ist, ORM-Framework zu verwenden, wie Lehre oder Propel (obwohl ich lieber Doctrine), die selbst komplexe Abfragen für Sie erledigen.

5

sollten Sie eine Zwischentabelle verwenden, die beiden Einheiten zu beziehen:

 
--------  1:n ------------   --------- 
| ITEM |-¦---------<| ITEM_TAG | n:1 | TAG | 
| Id |   | ItemId |>-------¦-| Id | 
| Name |   | TagId |   | Name | 
¯¯¯¯¯¯¯¯   ¯¯¯¯¯¯¯¯¯¯¯¯   ¯¯¯¯¯¯¯¯¯ 

dann die Daten für die Abfrage, sollten Sie Ihre Tabellen in einer select-Anweisung join:

alle Elemente in dem Tag "FooTag"

SELECT item.* FROM item 
       JOIN item_tag on item.id = item_tag.itemId 
       JOIN tag on item_tag.tagId = tag.id 
WHERE tag.Name = 'FooTag' 

Alle Tags für das Element mit dem Namen "FooItem "

SELECT tag.* FROM tag 
      JOIN item_tag on tag.id = item_tag.tagId 
      JOIN item on item_tag.itemId = item.id 
WHERE item.Name = 'FooItem' 
+0

schönes Diagramm :) +1 –

Verwandte Themen