2009-03-12 6 views
20

Ich spiele mit Zend Framework und versuche, den "QuickStart" Guide gegen eine Website zu verwenden, die ich mache, nur um zu sehen, wie der Prozess funktionieren würde. Verzeih mir, wenn diese Antwort offensichtlich ist, kann hoffentlich jemand, der etwas erlebt hat, etwas Licht in diese Sache bringen.Modellieren von Objekten mit mehreren Tabellenbeziehungen in Zend Framework

Ich habe drei Datenbanktabellen:

CREATE TABLE `users` (
    `id` int(11) NOT NULL auto_increment, 
    `email` varchar(255) NOT NULL, 
    `username` varchar(255) NOT NULL default '', 
    `first` varchar(128) NOT NULL default '', 
    `last` varchar(128) NOT NULL default '', 
    `gender` enum('M','F') default NULL, 
    `birthyear` year(4) default NULL, 
    `postal` varchar(16) default NULL, 
    `auth_method` enum('Default','OpenID','Facebook','Disabled') NOT NULL default 'Default', 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `email` (`email`), 
    UNIQUE KEY `username` (`username`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 

CREATE TABLE `user_password` (
    `user_id` int(11) NOT NULL, 
    `password` varchar(16) NOT NULL default '', 
    PRIMARY KEY (`user_id`), 
    UNIQUE KEY `user_id` (`user_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 

CREATE TABLE `user_metadata` (
    `user_id` int(11) NOT NULL default '0', 
    `signup_date` datetime default NULL, 
    `signup_ip` varchar(15) default NULL, 
    `last_login_date` datetime default NULL, 
    `last_login_ip` varchar(15) default NULL, 
    PRIMARY KEY (`user_id`), 
    UNIQUE KEY `user_id` (`user_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 

Ich möchte ein User-Modell erstellen, die alle drei Tabellen in bestimmten Situationen verwendet. Z. B. wird auf die Metadatentabelle zugegriffen, wenn/wenn die Metadaten benötigt werden. Auf die Tabelle user_password wird nur zugegriffen, wenn die 'auth_method'-Standardeinstellung festgelegt ist. Ich werde wahrscheinlich später eine Profiltabelle hinzufügen, auf die ich vom Benutzermodell aus zugreifen möchte.

Was ist der beste Weg, dies mit ZF zu tun und warum?

+0

Sehr unklar, warum dies abgelehnt wird: Gibt es ein Problem mit dieser Frage? Ich konnte keine ähnliche Frage finden, die das in dem Detail erklärt, nach dem ich suche. Lass es mich wissen, wenn ich klarer sein kann. –

+0

Keine Ahnung, vielleicht Datenüberschuss? Sie könnten das gesamte SQL durch eine kurze Beschreibung der Tabellen ersetzen. – vartec

+0

Scheint, dass jemand alle neuen Fragen abgelehnt hat – vartec

Antwort

23
class Users extends Zend_Db_Table_Abstract 
{ 
    protected $_name = 'users'; 
    protected $_rowClass = 'User'; 
    protected $_dependentTables = array ('UserMetadata', 'UserPassword'); 

... 

class UserMetadata extends Zend_Db_Table_Abstract 
{ 
    protected $_name = 'user_metadata'; 
    protected $_referenceMap = array (
    'Users'=> array (
    'columns'=>'user_id', 
    'refTableClass'=>'Users', 
    'refColumns'=>'id' 
    ) 
    ); 

... 

class UserPassword extends Zend_Db_Table_Abstract 
{ 
    protected $_name = 'user_password'; 
    protected $_referenceMap = array (
    'Users'=> array (
    'columns'=>'user_id', 
    'refTableClass'=>'Users', 
    'refColumns'=>'id' 
    ) 
    ); 

Daten abrufen:

$id = //get your user id from somewhere 

$users = new Users(); 
$user = $users->fetchRow('id=?', $id); 
if ($user->authMethod == 0) 
{ 
    $metadata = $user->findDependentRowset('UserMetadata')->current(); 
} 

oder

$user = $users->fetchRow($users->select() 
       ->where('gender=?, 'M') 
       ->order('email ASC'); 

... etc.

Einfügen von Daten:

$newRow = $users->fetchNew(); 
$newRow->email = [email protected]; 
$newRow->save(); 

oder

$users = new Users(); 
$data = array('email'  => '[email protected]', 
       'firstname' => 'Me'); 
$users->insert($data); 

Updating:

$user->email = '[email protected]'; 
$user->save(); 

Löschen einer Zeile:

$user->delete(); 

Mit der Transaktion:

$db->beginTransaction(); 
$db->commit(); 
$db->rollback(); 

etc ... es ist alles in den ZF Manual!

+0

Das macht für mich am meisten Sinn - also wie gehst du mit einer Einfügung in die Benutzertabelle um? Logischerweise sollte auch eine user_metadata-Zeile erstellt werden. Kann ich das irgendwie auf Modelebene handhaben? –

+1

Die Logik zum Erstellen einer Metadatenzeile beim Erstellen einer Benutzerzeile müssen Sie selbst schreiben. aber das ist einfach. Wenn Sie es sauber machen wollen, verwenden Sie Transaktionen ... – markus

+0

Dies ist genau das, was ich getan habe, und es hat ganz gut funktioniert. Vielen Dank. –

2

Verwenden Sie anstelle von Zend_Db_Table allgemeinere Zend_Db_Select oder Zend_Db_Statement, um Daten abzurufen.

BTW. Möglicherweise möchten Sie nicht direkt im Benutzermodell auf Kennwortdaten zugreifen, sondern in Ihrer von Zend_Auth_Adapter abgeleiteten Benutzerauthentifizierungsklasse.

+0

Ich habe nicht vor, über das Benutzermodell auf Passwortdaten zuzugreifen, außer um sie zu aktualisieren. Wird mit Zend_Db_Select die Idee, Benutzerdaten als einzelnes Objekt zu modellieren, nicht vollständig umgangen? –

+0

Es ist kein ORM, es ist kein 1-zu-1-Klassentabelle-Mapping erforderlich. – vartec

+0

BTW. Das 1 = 1-Mapping wäre möglich, wenn Ihre DB in 3NF wäre. Ihr Problem rührt daher, dass Sie Ihre DB denormalisiert haben und die Benutzerdaten in 3 Tabellen aufgeteilt haben. – vartec

0

Ich würde sagen, dass der beste Weg, dies mit ZF zu tun ist mit Doctrine.

0

Nur ein paar Notizen direkt von der Fledermaus:

Die erste Benutzertabelle, eher wie eine Person Tisch scheint, mit Ausnahme der Auth-Methode, aber man kann, dass in der Tabelle user_password setzen, die Sie wahrscheinlich umbenennen könnten Benutzer. Die Tabelle User_Metadata scheint so zu sein, als ob sie nur mit der Tabelle User_Password/User zusammengeführt werden könnte.

Jetzt, auch ohne diese Änderungen, haben Sie drei verschiedene Tabellen, mit drei verschiedenen Konzepten, wenn Sie jedes dieser als separate Klassen modellieren, und dann hatte eine UserModel-Klasse als eine Fassade von Arten auf jedes zugreifen, würde es wahrscheinlich machen es einfacher.

2

Kurz gesagt, ich würde ein Modell für jede Tabelle erstellen, nicht ein Modell, das auf alle drei zugreift. Ich würde dann define relationships zwischen den Tabellen.

Um ehrlich zu sein scheint es nicht sehr "DRY" zu sein, ein Modell für jede Tabelle zu erstellen, aber das sehe ich wiederholt in den verschiedenen Beispielen online und es ist das, was ich in den wenigen Projekten gemacht habe haben mit dem Zend Framework erstellt. Wenn jemand eine bessere Möglichkeit hat, damit umzugehen, hoffe ich, dass er es hier veröffentlichen wird.