2009-03-12 10 views
20

Je suis en train de jouer avec Zend Framework et j'essaie d'utiliser le guide "QuickStart" sur un site Web que je réalise juste pour voir comment le processus fonctionnerait. Pardonnez-moi si cette réponse est évidente, j'espère que quelqu'un d'expérimenté pourra nous éclairer là-dessus.Modélisation d'objets avec plusieurs relations de tables dans Zend Framework

J'ai trois tables de base de données:

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 

Je veux créer un modèle utilisateur qui utilise les trois tables dans certaines situations. Par exemple, la table de métadonnées est accessible si/quand les méta-données sont nécessaires. La table user_password n'est accessible que si la méthode auth_method 'Default' est définie. J'ajouterai probablement un tableau de profil plus tard auquel j'aimerais pouvoir accéder depuis le modèle utilisateur.

Quelle est la meilleure façon de le faire avec ZF et pourquoi?

+0

On ne sait pas très bien pourquoi cette question a été rejetée: y a-t-il un problème avec cette question? Je ne pouvais pas trouver une question similaire qui explique cela dans le détail que je cherche. Faites-moi savoir si je peux être plus clair. –

+0

Dunno, l'excès de données peut-être? Vous pouvez remplacer tout ce SQL avec une brève description des tables. – vartec

+0

Il semble que quelqu'un ait annulé toutes les nouvelles questions – vartec

Répondre

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' 
    ) 
    ); 

données enjoués:

$id = //get your user id from somewhere 

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

ou

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

... etc.

données Insertion:

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

ou

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

mise à jour:

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

Suppression d'une ligne:

$user->delete(); 

transaction utilisant:

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

etc ... il est dans le ZF Manual!

+0

Cela me semble plus logique - alors comment gérez-vous un insert dans la table des utilisateurs? Logiquement, une ligne user_metadata devrait également être créée. Puis-je gérer cela au niveau du modèle en quelque sorte? –

+1

Les logiques pour créer une ligne de méta-données lors de la création d'une ligne d'utilisateur que vous devez écrire vous-même. mais c'est facile. si vous voulez le faire à la manière propre utiliser des transactions ... – markus

+0

C'est exactement ce que j'ai fini par faire, et cela a très bien fonctionné. Je vous remercie. –

2

Fondamentalement, au lieu d'utiliser Zend_Db_Table utiliser plus général Zend_Db_Select ou Zend_Db_Statement pour récupérer des données.

BTW. Vous souhaiterez peut-être accéder aux données de mot de passe non directement dans le modèle utilisateur, mais plutôt dans votre classe d'authentification utilisateur dérivée de Zend_Auth_Adapter.

+0

Je ne prévois pas d'accéder aux données de mot de passe via le modèle utilisateur, sauf pour le mettre à jour. L'utilisation de Zend_Db_Select ne permet-elle pas de contourner complètement l'idée de modéliser les données utilisateur en tant qu'objet unique? –

+0

Ce n'est pas ORM, il n'y a pas besoin de mappage table-classe 1-à-1. – vartec

+0

BTW. le mappage 1 = 1 serait possible si votre BD était en 3NF, votre problème vient du fait que vous avez dénormalisé votre DB, en divisant les données utilisateur en 3 tables. – vartec

0

Je dirais que la meilleure façon de faire cela avec ZF est d'utiliser Doctrine.

0

Juste quelques notes directement au large de la chauve-souris:

La première table utilisateur, ressemble plus à une table de personne, sauf pour la méthode d'authentification, mais vous pouvez le mettre dans la table user_password, que vous pourriez probablement renommer Utilisateur. La table User_Metadata semble pouvoir être fusionnée avec la table User_Password/User. Maintenant, même sans ces changements, vous avez trois tables distinctes, avec trois concepts distincts, si vous modélisez chacune de ces classes comme des classes différentes, et que vous avez ensuite une classe UserModel comme une sorte de façade pour accéder à chacune d'entre elles, probablement le rendre plus facile.

2

En un mot je créerais un modèle pour chaque table, pas un modèle qui accède tous les trois. Je voudrais alors define relationships entre les tables. Pour être honnête il ne me semble pas très "DRY" de devoir créer un modèle pour chaque table mais c'est ce que je vois à plusieurs reprises dans les différents exemples en ligne et c'est ce que j'ai fait dans la poignée de projets que j'ai ont créé avec le Zend Framework. Si quelqu'un a une meilleure façon de gérer cela, j'espère que le postera ici.

Questions connexes