Datenbank-Design für Roles der Zend-ACL

Datenbank-Design für Roles der Zend-ACL

am 26.08.2007 12:15:20 von Michael Ziegler

Hallo,

ich bin im Moment dabei mir eine Klasse von Zend_ACL abzuleiten, welche
im Konstruktor die Resources, Roles und die Berechtigungen aus einer
MySQL-Datenbank liest. Dabei habe ich folgendes Problem:

Zend_ACL unterstützt Vererbung von Rechten zwischen den Roles. Dabei
kann eine Role Berechtigungen von beliebig vielen anderen Roles erben.
Um das in der Datenbank abzubilden, habe ich folgende Tabellen erstellt[1]:

+-------------+ +--------------+
| Roles | | Inheritance |
+-------------+ FK +--------------+
| *id |<-----| *child_id |
| ... | `--| *parent_id |
+-------------+ | order |
+--------------+

(Mit * markierte Felder gehören zum Primärschlüssel)

Die Tabelle Roles speichert einige Daten über die vorhandenen Roles, und
die Tabelle Inheritance kennt die Vererbung der Roles untereinander.
Dabei ist das Feld order von Bedeutung, da die Auswertung der
Berechtigungen auch davon abhängt, in welcher Reihenfolge die
Elternknoten einer Role angegeben werden.

Hier stellt sich mir die Frage: Ist das soweit sinnvoll, oder gibt es da
einen besseren Weg? Nested Sets haben soweit ich das gesehen habe die
Einschränkung, dass jeder Knoten maximal einen Vater haben kann, weshalb
ich sie nicht benutzen kann...


Bei diesem Design ergibt sich das Problem, dass ich die Ebene im
Vererbungsbaum nicht kenne, auf der sich ein Knoten befindet. Ich muss
aber sicherstellen können, dass die Zend_ACL bereits alle Roles kennt,
von denen die aktuelle Role Berechtigungen erben könnte, und dazu den
Baum ebenenweise traversieren. Wie kann ich die Elemente des Baumes so
selektieren, dass sie in der korrekten Reihenfolge in die ACL eingefügt
werden? (Ich brauche hier nur die ID der Roles.)

Dazu fällt mir nur ein, in der Tabelle "Roles" den Index der Ebene zu
speichern und dann danach per ORDER BY zu sortieren. Dann bräuchte ich
natürlich eine Möglichkeit, diesen Index rauszukriegen...

Gibt es für dieses Szenario eine elegante Lösung?

Vielen Dank und viele Grüße,
Michael




[1] Hier noch die Create-Statements für die beiden Tabellen:

CREATE TABLE `acl_roles` (
`id` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

CREATE TABLE `acl_inheritance` (
`child_id` varchar(50) NOT NULL,
`parent_id` varchar(50) NOT NULL,
`order` int(11) NOT NULL default '0',
PRIMARY KEY (`child_id`,`parent_id`),
KEY `parent_id` (`parent_id`),
CONSTRAINT `acl_inheritance_ibfk_3` FOREIGN KEY (`child_id`)
REFERENCES `acl_roles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `acl_inheritance_ibfk_4` FOREIGN KEY (`parent_id`)
REFERENCES `acl_roles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8