|
bituniverse.com Entwickler Forum
|
| Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
| Autor |
Nachricht |
Slava Administrator
Anmeldedatum: 16.01.2007 Beiträge: 282 Wohnort: Köln
|
|
| Nach oben |
|
 |
dr.e. Moderator
Anmeldedatum: 04.11.2007 Beiträge: 98
|
Verfasst am: So 25 Nov, 2007 23:41 Titel: |
|
|
Folgende Hinweise:
- Rollen sollten eine Sammlung von Berechtigungen auf Funktionen sein
- Die Qualität von Rechten sollte man in den Beziehungen speichern, bzw.
unterschiedliche Beziehungen für das Recht "Löschen", "Bearbeiten", ...
definieren.
Das Tabellendesign ist zudem ein wenig ungenerisch, da man so etwas wie Rechte auf Objekte vergeben können sollte.
_________________
Grüße,
Dr.E.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Have a look at www.adventure-php-framework.org!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| Nach oben |
|
 |
Simon W. Anti-verdenglischungs-Abgeordneter
Anmeldedatum: 05.11.2007 Beiträge: 283 Wohnort: Aachen
|
Verfasst am: Mo 26 Nov, 2007 01:29 Titel: |
|
|
Ja, wir bräuchten ein System, das mit mehreren Bereichen umgehen kann und nicht nur auf eine Forenstruktur zugeschnitten ist. Jedes Modul(Bereich) sollte unabhängig Rechte für bestimmte Aktionen abfragen und setzen können und das wiederum abhängig von "Objekten", wie dr.e. es nannte.
|
|
| Nach oben |
|
 |
Slava Administrator
Anmeldedatum: 16.01.2007 Beiträge: 282 Wohnort: Köln
|
Verfasst am: Mi 28 Nov, 2007 02:18 Titel: |
|
|
| dr.e. hat Folgendes geschrieben: |
Folgende Hinweise:
- Rollen sollten eine Sammlung von Berechtigungen auf Funktionen sein
- Die Qualität von Rechten sollte man in den Beziehungen speichern, bzw.
unterschiedliche Beziehungen für das Recht "Löschen", "Bearbeiten", ...
definieren.
Das Tabellendesign ist zudem ein wenig ungenerisch, da man so etwas wie Rechte auf Objekte vergeben können sollte. |
ich kann das auch ginerisch machen um eine universale Lösung zu haben (die ACL Konzepte sind mir bekannt) , dann ist aber die performance hin. wir dürfen nicht vergessen, dass die Resource in unserem Fall eine tabellenzeile ist, und ich kann mir leider nicht leisten für jede zeile eine extra ACL abfrage starten.
zu viele Abstractionen brauchen wir gar nicht.
es wird eine Model mit einer methode erstellt, die nötige Informationen liefert. es geht um Forum und die Tabellen werden auch für Forum gemacht (mit ausname von User-tabelle)und zwar so, dass wir auch Performancemassig in grünem bereich liegen.
Wenn wir datenmodel erstellen, bin ich eigentlich dafür, dass nur wenige Leute die Model-classe mit passenden Methoden erstellen.
Alle andere nutzen das nur, und brauchen sich erst mit den technischen fragen von DB-Abfragen gar nicht bescheftegen, ob die Daten von DB oder Cach kommen ist erst für die Jenige, die mit Controller und View beschäftigen unrelevant. Wir müssen noch ganu nachschauen, wie viele querys eigentlich benötigt werden, und wenn das zu viele sind, wird vermutlich die Model-Classe die einzelne Methoden zum laufzeit laden (bzw in mehrere Models geteilt) um die Anwendung zu entlasten (das selbe gilt auch für die Controller).
Wir versuchen gerade mit dem Jens verschiedene Varianten durch Kopf zu jagen um ein optimaler Weg zwischen Geschwindigkeit, Verständlichkeit von Code und Anpassungsfähigkeit von software zu ermöglichen. Vermutlich werden wir auch die Massnamen treffen , die nicht unbedingt an die allgemeine Vorstellung von Datenhaltung entsprechen um Datenbank zu schönen und der Einsatz von software auch bei biliganbieter zu ermöglichen.
|
|
| Nach oben |
|
 |
dr.e. Moderator
Anmeldedatum: 04.11.2007 Beiträge: 98
|
Verfasst am: So 02 Dez, 2007 15:50 Titel: |
|
|
Hallo Slava,
| Zitat: |
zu viele Abstractionen brauchen wir gar nicht.
es wird eine Model mit einer methode erstellt, die nötige Informationen liefert. es geht um Forum und die Tabellen werden auch für Forum gemacht (mit ausname von User-tabelle)und zwar so, dass wir auch Performancemassig in grünem bereich liegen. |
Da würde ich vorsichtig sein, denn meiner Einschätzung nach sind die Anforderungen noch nicht wirklich klar definiert. In diesem Fall muss man mehr Generik walten lassen um spätere Erweiterungen auch implementieren zu können. Hier sollte man auch hinsichtlich der GUI möglichst frei in seiner Erweiterbarkeit bleiben, denn neue Features können sonst eine komplette Überarbeitung notwenig machen.
| Zitat: |
| Alle andere nutzen das nur, und brauchen sich erst mit den technischen fragen von DB-Abfragen gar nicht bescheftegen, ob die Daten von DB oder Cach kommen ist erst für die Jenige, die mit Controller und View beschäftigen unrelevant. Wir müssen noch ganu nachschauen, wie viele querys eigentlich benötigt werden, und wenn das zu viele sind, wird vermutlich die Model-Classe die einzelne Methoden zum laufzeit laden (bzw in mehrere Models geteilt) um die Anwendung zu entlasten (das selbe gilt auch für die Controller). |
Das ist ein gutes API-Konzept. Man sollte an dieser Stelle einen usermanagementManager bereitstellen, der einem die notwenigen Information geben kann. Das sind (sicher nicht vollständig):
- getUserByID(): Alle Daten zu einem Benutzer. Von diesem User-Objekt kann man sich dann die Gruppen, ACLs, ... geben lassen
- getUserList(): Liste von Benutzern für diverse Anzeigen. Man sollte der Methode noch mitgeben können welche Attributre u.U. mitgeladen werden sollen (ACLs, Gruppen, ...), damit man performancetechnisch gut gewappnet ist.
- getGroupByID(): Selbe Implementierung wie für Benutzer
- getGroupList(): Selbe Implementierung wie für Benutzer
- getRoleByID(): Rolle mit ihren ACL-Definitionen liefern
- getRoleList(): Liste der Rollen, Implementierung wie bei Benutzern
- getUsersByGroup(): Liste von Benutzern per Gruppe liefern
- getUsersByRole(): Liste von Benutzern per Rolle liefern
- save*(): Speicherung von Objekten
Der Anwender kann dann einfach den Manager verwenden und muss sich um den Rest nicht kümmern. Wichtig ist dabei, dass sich die Business-Schicht um die Auflösung der Beziehungen und die Datenschicht um die Datenhaltung kümmert. Nehmen wir an, dass ein Benutzer mit einer neuen Gruppe ausgestattet worden ist, dann muss das die Business-Schicht erkennen und die neue Gruppe speichern, ehe die Beziehung zwischen Benutzer und Gruppe aufgebaut werden kann.
Alles in allem sehr komplex und zum Thema Performance nicht gerade ein einfaches Unterfangen. Sollte ich zu diesem Bereich etwas beitragen können, bitte melden.
-
-
_________________
Grüße,
Dr.E.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Have a look at www.adventure-php-framework.org!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| Nach oben |
|
 |
Slava Administrator
Anmeldedatum: 16.01.2007 Beiträge: 282 Wohnort: Köln
|
Verfasst am: Do 13 Dez, 2007 01:26 Titel: |
|
|
so
jetzt mache ich mir ernst die Gedanken über Usermanagement.
Wie schon alle bemerkt haben ist es natürlich optimal ein object oder eine funktion als Resource zu definieren, die ein bestimter Satzt von Rechten hat.
Dan würde ein User, Bzw Usergroup eine Rolle bekommen, die zu einer Resource ein bestimmter Rechten-Set hat.
bei diesem Perfektem fall, wäre es sehr leicht alles zu defenieren.
Ich könnte schon wärend Dispatching-prozess die benötigte RechtenSet zu dem Angefördertem Controller->acrionMethod anfördern, der als Resource deklariert ist.
Wie sieht es jetzt aber aus mit einzelner Tabellenzeile?
Zbs Forumsübersicht oder jeder einzelner Posting.
ich muss jede einzelne Zeile als ein Object betrachten und zusätzliche infos anfördern.
In diesem Fall muss ich ein Objectorientierte schicht über Datenbank ziehen, die es erlaubt jede einzelne Zeile als getrennte Resource zu betrachten. Dabei wird es bei manchen Stellen, wie zbs Posting nicht nur auf Groupenebene, sondern auch Userebene unterschiede geben (user darf sein posting editieren).
Schaut mal wie viele ACL es geben kann
1)Forumübersicht
ACL-1 Gruppe zu jeder einzelner ForumNamen Zeile (lesen,bearbeiten,löschen)
ACL-2 Gruppe zu Tabelle ForumNamen (nur für einfügen)
ACL-3 Gruppe zu Controller selbst (ausführen)
ACL-4 Gruppe zu Modul (ansehen)
2)ThreadÜbersicht
ACL-1 Gruppe + User zu Thread-Zeile(lesen,löschen,moderieren,verschieben,bearbeiten)
ACL-2 Gruppe zu Thread-Tabelle (einfügen)
ACL-3 Controller, Method, Modul (lesen)
.......
Also eine ganze Menge von Rechten, die Teilweise gar nicht über Usermanagement-Tool sondern direkt bei Programmieren fest implementiert.
Jetzt kommt die Frage wie schwer das alles zu machen ist. also auf sql-ebene kann ich mir das Gut vorstellen. Werden wir aber darüber viel zu viel abstracten Schichten ziehen, dann werden wir schnell feststellen, dass dieser Weg uns keine Vorteile bringt und macht schnell die Anwendung unübersichtlich.
die von Dr.e vorgeschlagene Methoden sind natürlich sehr wichtig, aber die meiste von diesen Methoden werden kaum alleine aufgerufen, sondern als ein Teilmenge von einer Sql-Abfrage, da ich mich für eine Rolle erst dann interessiere, wenn ich eine Resource und seine Rechte habe, auf die die Rolle zugreifen möchte. Werde ich an dieser Stelle von Sql in die Richtung von verständlichen und passenden Objecten und Methodennamen abweichen, dann werde ich gezwungen die reqrusive sqlabfragen im Hintergrund zu jagen, was sehr viel Performance in Anspruch nimmt und auch eine Menge von zusätzlichen Classen programmieren.
Zum Usermanagement:
ich schlage vor, dass wir User-tabelle nicht unbedingt als Forumuser-Tabelle betrachten, da es vorkommen kann, dass wir die Userdaten auch bei zukunftigen Modulen verwenden können.
Usermanagement muss meine Meinung nach so programmiert werden, dass wir die User bezogene(User_id,Name, email, icq_nr...) und forum-user bezogene Daten (Nikname, Signatur,...) trennen könnten.
|
|
| Nach oben |
|
 |
dr.e. Moderator
Anmeldedatum: 04.11.2007 Beiträge: 98
|
Verfasst am: Do 13 Dez, 2007 10:37 Titel: |
|
|
Hallo Slava,
bei deinen Betrachtungen muss du aufpassen, dass du zwischen Gruppen und Rollen unterscheidest. Eine Rolle wiederum beinhaltet verschiedene Permissions. Eine Permission ist das "Recht" eine Funktion innerhalb einer Applikation auszuführen. Dieses "Recht" ist natürlich hardcoded in der Applikation drin, denn die Applikation implementiert diese Funktionen ja.
Wie hinterher das Datenbank-Layout aussieht ist ersmal unabhängig der Betrachtung der API des Usermanagers. Dieses sollte die von mir vorgeschlagenen Methoden haben, mit im Action-Controller verwendet werden können (z.B. Laden der Permissions eines Benutzers). Wie du das hinterher allgemein zur Verfügung stellst, sprich ob eine Instanz des Benutzer-Objekts jedem Action-Controller mitgegeben wird, ist eine andere Sache.
//EDIT:
Nochmal grundsätzlich zum Entwicklungsprozess derartiger Module: du musst dir immer zuerst die API überlegen, dann die interne Strukturierung desselben und dann erst die Datenbank-Strategie. Diese Vorgehendweise entspricht einem Top-Down-Approach, der den Vorteil hat, dass du das Tabellen-Desig unabhängig vom verhalten hinterher machen kannst.
_________________
Grüße,
Dr.E.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Have a look at www.adventure-php-framework.org!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| Nach oben |
|
 |
Slava Administrator
Anmeldedatum: 16.01.2007 Beiträge: 282 Wohnort: Köln
|
Verfasst am: Do 13 Dez, 2007 20:03 Titel: |
|
|
| dr.e. hat Folgendes geschrieben: |
Hallo Slava,
bei deinen Betrachtungen muss du aufpassen, dass du zwischen Gruppen und Rollen unterscheidest. Eine Rolle wiederum beinhaltet verschiedene Permissions. Eine Permission ist das "Recht" eine Funktion innerhalb einer Applikation auszuführen. Dieses "Recht" ist natürlich hardcoded in der Applikation drin, denn die Applikation implementiert diese Funktionen ja.
|
Hi Dr.e.
wie würdest du an die Sache gehen?
Wenn wir jetzt ein Klassischer ACL beispiel zbs von ZendFramework nehmen framework.zend.com
es ist klar, dass wie ich es objectorientiert machen kann, aber ich ich weis nicht ganz, wie ich das auf Db-ebene mit passender Performance an die vorprogrammierte ACL Objecte binde. Ich will nicht sagen, dass es nicht möglich ist, aber mir fehlt irgendwie Faden um das ginerisch zu realisieren.
Zu Usermanagement:
Ich stelle mir das so vor.
---------------
User und ForumUser
Tabelle User wird Name, Vorname, User_id, E-Mail, icq_nr, ....
bekommen.
Tabelle Forum_User wird mit User durch User_id verknüpft und wird nur forumbezogene Sachen , wie Nikname, Signatur erhalten.
das wird für uns ein Zusätzlicher Join bedeuten, wird aber erlauben die Tabelle User in anderen Modulen verwenden.
Wird jemand sich entscheiden ein Onlineshop zu programmieren, dann kann er automatisch die User in Forum reinlassen.
---------------------------------
Verwaltung
Globale userbezogene Informationen ändern bzw bearbeiten.
Name, Email, Adresse, von Tabelle User muss getrennt von ForumUser bearbeitet werden.
Grupenverwaltung.
(Gruppenverwaltung muss man nicht unbedingt nur in Zusammenhang mit dem Forum betrachten)
1) neue gruppe erzeugen
2) gruppe editieren und löschen.
3) User an eine Gruppe binden, bzw löschen
-------------
Die Tabellenstruktur für Gruppen, User und Forumuser werde ich Heute vorbereiten.
OT
Ich warte noch, was Jens mit meinem Code einrichtet (ich bin mir jetzt nicht siecher, dass da noch meine code drin steht )
Wenn die Tabellenstruktur von dem Forum selbst und die Resourcen, die betimmte Rechte fordern klar sind, dann werden wir bei Usermanagement zusetzlich die Rechteverwaltung machen müssen.
|
|
| Nach oben |
|
 |
Slava Administrator
Anmeldedatum: 16.01.2007 Beiträge: 282 Wohnort: Köln
|
Verfasst am: Fr 14 Dez, 2007 12:19 Titel: Tabellenstruktur |
|
|
bitte der sternchen im se* durch 'x' ersetzen :)
| Code: |
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `forum_user`
--
CREATE TABLE IF NOT EXISTS `forum_user` (
`user_id` int(8) NOT NULL,
`user_active` tinyint(1) default '1',
`user_lastvisit` int(11) NOT NULL,
`user_timezone` decimal(5,2) NOT NULL default '0.00',
`user_viewemail` tinyint(1) NOT NULL default '0',
`user_newpasswd` varchar(32) collate utf8_unicode_ci default NULL,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Daten für Tabelle `forum_user`
--
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `groups`
--
CREATE TABLE IF NOT EXISTS `groups` (
`group_id` int(8) NOT NULL auto_increment,
`group_name` varchar(40) collate utf8_unicode_ci NOT NULL,
`group_description` varchar(255) collate utf8_unicode_ci NOT NULL,
PRIMARY KEY (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
--
-- Daten für Tabelle `groups`
--
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `users`
--
CREATE TABLE IF NOT EXISTS `users` (
`user_id` int(11) NOT NULL default '0',
`username` varchar(64) collate utf8_unicode_ci default NULL,
`passwd` varchar(32) collate utf8_unicode_ci default NULL,
`first_name` varchar(128) collate utf8_unicode_ci default NULL,
`last_name` varchar(128) collate utf8_unicode_ci default NULL,
`user_lang` char(2) collate utf8_unicode_ci default NULL,
`se*` set('m','f') collate utf8_unicode_ci default NULL,
`birth_date` date default NULL,
`telephone` varchar(16) collate utf8_unicode_ci default NULL,
`mobile` varchar(16) collate utf8_unicode_ci default NULL,
`email` varchar(128) collate utf8_unicode_ci default NULL,
`user_icq` varchar(15) collate utf8_unicode_ci default NULL,
`user_msn` varchar(40) collate utf8_unicode_ci default NULL,
`user_skype` varchar(40) collate utf8_unicode_ci default NULL,
`webaddr` varchar(128) collate utf8_unicode_ci default NULL,
`addr` varchar(128) collate utf8_unicode_ci default NULL,
`city` varchar(64) collate utf8_unicode_ci default NULL,
`region` varchar(32) collate utf8_unicode_ci default NULL,
`country` char(2) collate utf8_unicode_ci default NULL,
`post_code` varchar(16) collate utf8_unicode_ci default NULL,
`is_email_public` smallint(6) default NULL,
`is_acct_active` smallint(6) default NULL,
`date_created` datetime default NULL,
`last_updated` datetime default NULL,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Daten für Tabelle `users`
--
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `user_groups`
--
CREATE TABLE IF NOT EXISTS `user_groups` (
`users_id` int(11) NOT NULL,
`groups_id` int(11) NOT NULL,
UNIQUE KEY `ug` (`users_id`,`groups_id`),
KEY `groups_id` (`groups_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Daten für Tabelle `user_groups`
--
--
-- Constraints der exportierten Tabellen
--
--
-- Constraints der Tabelle `forum_user`
--
ALTER TABLE `forum_user`
ADD CONSTRAINT `forum_user_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Constraints der Tabelle `user_groups`
--
ALTER TABLE `user_groups`
ADD CONSTRAINT `user_groups_ibfk_4` FOREIGN KEY (`groups_id`) REFERENCES `groups` (`group_id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `user_groups_ibfk_3` FOREIGN KEY (`users_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
| Nach oben |
|
 |
dr.e. Moderator
Anmeldedatum: 04.11.2007 Beiträge: 98
|
Verfasst am: Sa 15 Dez, 2007 13:56 Titel: |
|
|
Hallo Slava,
| Zitat: |
| wie würdest du an die Sache gehen? |
Hatte gedacht, dass der Ansatz bereits angekommen ist, ich versuche es aber nochmal verständlich rüberzubringen:
Grundlage allen Handelns ist der TOP-Down-Approach. Dieser beschreibt, dass ich ein Teilsystem von oben her entwerfe. Das bedeutet, dass ich mir zunächst die API überlege, die ich später brauchen werde. Dazu müssen selbstverständlich alle möglichen Anforderungen an die API definiert sein. Um das am konkreten Beispiel machen zu können lege ich einfach mal ein paar Anforderungen fest:
- Erstellen, Bearbeiten und Löschen von Benutzern
- Erstellen, Bearbeiten und Löschen von Gruppen
- Erstellen, Bearbeiten und Löschen von Berechtigungen
Dabei sind 3 Arten von Objekten interessant:
- Benutzer
- Gruppe
- Rolle
- Berechtigung
Die API sieht nun vor, dass man eine zentrale Klasse "userManagementManager" hat, die einem eine zentrale API für das Handling der oben genannten Objekte bereitstellt. Diese muss Methoden haben, wie ich sie bereits weiter oben angeführt hab. Ein Auszug sei nochmal hier aufgeführt:
- getUserList()
- getUserByID()
- getGroupList()
- getGroupByID()
Für das Benutzer-Objekt sollte es dann die Methoden
- getGroup()
- getPermissions()
- ...
geben. Diese Methoden ermöglichen z.B. schon das Laden einer Mitgliederliste und das Laden eines Benutzers. In den Rollen stecken entsprechende Berechtigungen, die definieren, welche Funktionen ausgeführt werden. Um das nochmal implementierungstechnisch zu verdeutlichen, ein kleines Beispiel, das zeigt, wie man innerhalb einer Software solche Rechte prüft. Beispiel soll ein Menü sein:
| Php: |
<?php
import('sites::forum::biz','userManagementManager');
import('sites::forum::biz','forumManager');
class MenuController extends baseController
{
function MenuController(){
}
function transformContent(){
// UserManagementManager holen
$uMM = &$this->__getServiceObject('sites::forum::biz','userManagementManager');
$User = $uMM->getUserByID($_SESSION['UserID']);
$Permissions = &$User->getPermissions(); // Array von Permissions
// Menu laden
$fM = &$this->__getServiceObject('sites::forum::biz','forumManager');
$Menu = $fM->loadMenu(); // Array von Menu-Punkten
// Menu zusammenbauen
$Buffer = (string)'';
foreach($Menu as $MenuObject){
if($MenuObject->get('PermissionOnly') == true){
if($Permissions[$MenuObject->get('PermissionKey')] == true){
$Buffer .= $MenuObject->get('DisplayName').'<br />';
}
}
}
// Puffer in den Platzhalter des aktuellen Templates setzen
$this->setPlaceHolder('Menu',$Buffer);
}
}
?>
|
Programmablauf sollte soweit klar sein. Ich habe das aus einem vorhanden Controller eines Programmes kopiert und modifiziert, deswegen sind hier Methoden des APF's (siehe Footer) enthalten. Der Verständlichkeit sollte das aber keinen Abbruch tun. Die Funktionen im einzelnen:
- Zunächst wird eine Instanz des userManagementManagers geholt und dieser zum Laden des aktuellen Users und dessen Berechtigungen verwendet.
- Die Berechtigungen sind nichts anderes als eine Liste mit Schlüsseln und einem Wert (true|false|...), die im Programm ausgewertet werden können.
- In der Implementierung bin ich oben bereits davon ausgegangen, dass jeder Menüpunkt einen sog. Permission-Key hat, den ich hinterher in den Permissionsets verwenden kann und so den Quellcode nicht ändern muss. Man kann das aber auch etwas ungenerischer anstellen und z.B. ein Adminmenü komplett abiffen in dem man einfach fragt:
| Php: |
<?php
if($Permissions['showAdminMenu'] == true){
...
}
?>
|
- Das Menü wird zunächst in einem Puffer zusammengesetzt und dann in einen Platzhalter geschrieben damit es angezeigt wird (Templating).
Die Definition der API ist an dieser Stelle abgeschlossen und wir müssen uns um die interne Implementierung kümmern. Um das Ganze einfach aber doch generisch zu halten verwende ich für die Tabellen definition einfache FK-Beziehungen statt eigene Beziehungstabellen. Das sieht wie folgt aus:
- Tabelle Benutzer (mit allen Attributen des Benutzers)
- Taballe Gruppen
- Tabelle Rolle
- Tabelle Berechtigungen
Die Benutzertabelle hat jeweils (der Einfachheit wegen) einen Frendschlüssel auf die Rollen- und Gruppen-Tabelle, damit die Zuordnung zwischen Benutzer, Gruppe und Rolle geregelt ist. Die Berechtigungen-Tabelle beinhaltet die Berechtigungsdefinitionen in der Form KEY=VALUE, d.h. 3 Spalten:
- PermissionID
- PermissionKey
- PermussionValue
- PermissionRole
Die letzte Spalte ist die Referenz auf eine Rolle und damit kann ich mir ganz einfach die Permissions selektieren, die zu einem Benutzer gehören, da die Rollen-ID sowohl in der Benutzer-Tabelle, als auch in der Berechtigungstabelle vorhanden ist.
Das Design hat natürlich den Nachteil, dass einem Benutzer nur eine Gruppe und eine Rolle zugewiesen werden kann, was im täglichen Leben häufig zu Problemen wie Mehrfachdatenhaltung führt, weil Rollen - wenn sie sich auch nur um eine Permission unterscheiden - doppelt angelegt werden müssen. Davon sehe ich aber mal ab.
Um eine noch bessere Trennung zwischen eigentlicher Geschäftslogik und Datenhaltung erreichen zu können möchte ich eine weitere Klasse einführen: den userManagementMapper. Dieser soll die Daten (Objekte Benutzer, Gruppe, Rolle, ...) aus der Datenbank lesen und dem Manager zur Verfügung stellen. Das Beispiel des Ladens des Benutzers würde dann ungefähr wie folgt aussehen:
| Php: |
<?php
import('sites::forum::data','userManagementMapper');
class userManagementManager extends coreObject
{
private $__UserCache = array();
function userManagementManager(){
}
function getUserByID($UserID){
if(isset($this->__UserCache [$UserID])){
return $this->__UserCache[$UserID];
}
// Datenschicht-Komponente holen
$uMM = &$this->__getServiceObject('sites::forum::data','userManagementMapper');
// Benutzer laden
$User = $uMM->loadUserByID($UserID);
// Gruppe laden
$User->set('Group',$uMM->loadGroupByID($User->get('GroupID')));
// Rolle laden
$User->set('Role',$uMM->loadRoleByID($User->get('RoleID')));
// Benutzer in der Komponente Cachen
$this->__UserCache[$UserID] = $User;
// Benutzer zurückgeben
return $User;
}
}
class userManagementMapper extends coreObject
{
function userManagementMapper(){
}
function loadUserByID($UserID){
}
function loadGroupByID($GroupID){
// Statement erzeugen
$select = 'SELECT * FROM group WHERE group_id = \''.$GroupID.'\';';
// Statement ausführen und Daten holen
// Array in Objekt mappen und zurückgeben
return $this->__mapGroup2DomainObject($data);
}
function loadRoleByID($RoleID){
}
private function __mapGroup2DomainObject($Result){
// Gruppen-Objekt instanziieren
$Group = new Group();
// Attribute setzen
$Group->set('ID',$Result['group_id']);
$Group->set('Name',$Result['name']);
// Gefülltes Domain-Objekt zurückgeben
return $Group;
}
}
?>
|
Ich hoffe der Design-Ansatz wird nun ein wenig klarer. Wenn man eine Mehrfachzuordnung machen möchte, muss das Datenmodell noch weiter normalisiert werden. Hier empfiehlt sich, die Beziehungen in eigene Tabellen auszulagern und die Objektattribute in einer Tabelle zu halten. Aus der Beziehung zwischen Benutzer und Gruppe werden dann 3 Tabellen:
- Benutzer
- Beziehungstabelle
- Gruppe
Somit ist eine n:m-Beziehung einfach möglich und mit ein paar INNER JOINs lassen sich die Daten einfach selektieren.
_________________
Grüße,
Dr.E.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Have a look at www.adventure-php-framework.org!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| Nach oben |
|
 |
|
|
Du kannst Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
Powered by phpBB © 2001, 2005 phpBB Group Deutsche Übersetzung von phpBB2.de
|