Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Pages: 1 2
Salut,
Perso c'est ce que je fait.
J'avoue ne pas avoir bien saisi :
sekaijin a écrit:
pas tout a fait le modèle doit encapsuler la couche de persistance
@++ Kaimite
Hors ligne
Le QuickStart actuel (v1.8) du Zend Framework est très intéressant pour faire un modèle bien fait.
Il suggère d'utiliser des Mapper.
Le Mapper est un objet qui encapsule la couche de persistance : c'est lui qui va gérer tous les Zend_Db_Table, Zend_Db_Table_Row, etc.
A partir de ces objets, le Mapper va construire des objets métier (des classes toutes simples qui ne contiennent que des attributs et pas de méthodes).
Et enfin, le contrôleur ne connaît et ne fait appel qu'au Mapper (pour récupérer/enregistrer des objets métier).
Voilà pour l'idée générale, maintenant les bienfaits de cette façon de faire :
- La vue n'a pas accès à la couche de persistance : on passe des objets métier à la vue, mais comme il n'y a aucune méthode sur ces objets, elle ne peut que les afficher et les repasser à un contrôleur.
- Les objets métier peuvent être sérialisés avec Zend_Dojo ou Zend_Amf par exemple. Ils sont super légers et n'ont que des attributs, pas de méthode. On est sûr de pouvoir les sérialiser sans erreur.
- On peux modifier la base de donnée sans modifier ni les objets métier, ni le contrôleur, ni la vue. On a que le Mapper à adapter. On a donc isolé le métier de la façon d'optimiser le stockage des données.
Voilà, j'espère que j'ai pu aider. Le principal défaut du Zend Framework je pense, c'est de ne pas proposer de Mapper Abstrait qui gèrerait déjà les opérations CRUD et les jointures... ce qui oblige soit à créer son propre Mapper Abstrait (pour les warriors), soit à se palucher toutes les opérations pour chaque Mapper... Bref, un défaut, mais l'idée est peut être déjà en développement ? En fait, c'est le cas ^^
Dernière modification par ramos (18-06-2009 11:57:36)
Hors ligne
ramos tu as un exemple concret de ce que pourrait contenir le mapper ? et le rapport au zend_table et zend_row ...
Hors ligne
Oui, regarde le Quickstart de Zend Framework section Model and Database.
Dedans il y a un Mapper très simple.
Par contre, écrire tous les mappers comme celui là peut être fastidieux. J'attends avec impatience un composant genre Zend_Mapper qui fera une partie du boulot à ma place ^^
Hors ligne
Salut,
J'ai regardé le code et il me vient une question bete...
Je vois souvent cette écriture
funtion getEmail () { return $this -> email; } ... $email = $user -> getEmail();
Pourquoi ne pas faire directement
$email = $user -> email;
Est-ce uniquement valable dans le vas ou la propriété serait private ou protected ?
Merci pour vos réponse.
Cordialement,
Kaimite
Hors ligne
Perso, je m'en sers par la suite si je veux faire des modifications dans la valeur qui doit être retuorné
Dans le cas d'un email, ca pourrait être un filtre par exemple
Ca m'évite à modifier tout mon code
Hors ligne
oki,
De mon coté j'utilise une méthode :
renvoyerInfosPourXXX () { }
La plupart du temps c'est renvoyerInfosPourWeb() et elle me renvoi un tableau associatif avec toutes les valeurs filtrées et préparées.
Je viens de recevoir une base avec une table de 72 champs et je trouve un peu galère de devoir faire 72 méthodes :
getXXX()
D'ailleurs a ceux qui utilisent cette méthode, utilisez vous une solution "automatisée" pour ce genre de grosses table ?
Merci pour les réponses.
Cordialement,
Kaimite
Hors ligne
Salut Kaimite,
La plupart du temps, il est bon d'utiliser des attributs privés (ou protected) et mettre en place des getters-setters dès le début.
La raison, c'est que tu pourra plus tard ajouter un traitement avant de renvoyer la valeur, sans avoir à modifier toutes les classes qui font appel à l'attribut email pour ton exemple.
C'est bien la plupart du temps, c'est extrêmement utilisé en Java, mais parfois ça ne sert à rien, voire génant (exemple : pour sérialiser une classe pour la passer à un framework comme GWT ou Flex, les attributs de cette classe doivent être public).
Typiquement, pour ta table de 72 colonnes, tu n'utilises pas de getter setter pour les attributs. Si tu utilises Zend_Db_Table, tu récupères un Zend_Db_Table_Row et les colonnes sont directement accessibles (soit par $row->email, soit par $row['email']). C'est un cas où justement les getter setter ne sont pas judicieux, à mon avis.
Enfin, on parlait de mapper tout à l'heure. Ce mapper utilise une Zend_Db_Table, et là c'est judicieux de faire un getTable() dans le mapper.
Hors ligne
oki.
Merci pour la réponse.
Je commence a mieux cerner tout ça
Encore un truc a regarder de plus près ! c'est ajouté dans la liste "à faire un jour ou l'autre"
Cordialement,
Kaimite
Dernière modification par Kaimite (19-06-2009 10:28:07)
Hors ligne
Kaimite a écrit:
oki,
De mon coté j'utilise une méthode :Code:
renvoyerInfosPourXXX () { }La plupart du temps c'est renvoyerInfosPourWeb() et elle me renvoi un tableau associatif avec toutes les valeurs filtrées et préparées.
Je viens de recevoir une base avec une table de 72 champs et je trouve un peu galère de devoir faire 72 méthodes :
getXXX()
D'ailleurs a ceux qui utilisent cette méthode, utilisez vous une solution "automatisée" pour ce genre de grosses table ?
Merci pour les réponses.
Cordialement,
Kaimite
__call est ton amis
Zend_dB doit surement l'utilisé pour des méthodes du type findOneById, findOneByName, ...
Hors ligne
ramos a écrit:
Salut Kaimite,
La plupart du temps, il est bon d'utiliser des attributs privés (ou protected) et mettre en place des getters-setters dès le début.
La raison, c'est que tu pourra plus tard ajouter un traitement avant de renvoyer la valeur, sans avoir à modifier toutes les classes qui font appel à l'attribut email pour ton exemple.
C'est bien la plupart du temps, c'est extrêmement utilisé en Java, mais parfois ça ne sert à rien, voire génant (exemple : pour sérialiser une classe pour la passer à un framework comme GWT ou Flex, les attributs de cette classe doivent être public).
Typiquement, pour ta table de 72 colonnes, tu n'utilises pas de getter setter pour les attributs. Si tu utilises Zend_Db_Table, tu récupères un Zend_Db_Table_Row et les colonnes sont directement accessibles (soit par $row->email, soit par $row['email']). C'est un cas où justement les getter setter ne sont pas judicieux, à mon avis.
Enfin, on parlait de mapper tout à l'heure. Ce mapper utilise une Zend_Db_Table, et là c'est judicieux de faire un getTable() dans le mapper.
Je ne sais pas comment est codé Zen_Db_* car je ne l'utilise pas.
Mais dans Doctrine, tu peux faire $row->email et $row['email'] et $row->getEmail() et $row->get('Email'). Tous les attributs sont protégés, il utilise des méthodes magiques et implémente les interfaces nécessaires au PHP. Dans tous les cas, tu peux rajouté toi-même une fonction getEmail pour faire un filtre, et donc, quelques soit la méthode que tu utilises ton getter sera utilisé comme proxy. (et encore, j'abrège la)
Hors ligne
ramos a écrit:
- Les objets métier peuvent être sérialisés avec Zend_Dojo ou Zend_Amf par exemple. Ils sont super légers et n'ont que des attributs, pas de méthode. On est sûr de pouvoir les sérialiser sans erreur.
De toute façon, quand tu sérialises un objet, il n'y a que les variables (et le nom de la classe) qui sont enregistrées (c'est d'ailleurs pour ça que la classe doit être incluse pour réveiller l'objet), donc l'argument pas de méthodes ne tient pas.
Hors ligne
Kaimite a écrit:
Je viens de mettre à jour mon ZF avec la version 1.6 et j'ai testé le Zend_Paginator.
Très simple à mettre en place et à utiliser
Au niveau des requêtes ça ne change pas grand chose :Code:
SELECT COUNT(*) AS zend_paginator_row_count FROM `tbl_articles` SELECT `tbl_articles`.`uid` FROM `tbl_articles` LIMIT 10 OFFSET 80En tout cas c'est très simple à mettre en place !
Bonjour,
Pour rebondir sur la question de la gestion de la pagination en minimisant l'impact des requêtes sur les performances, il existe une fonction SQL, nommée SELECT FOUND_ROWS, qui permet de calculer le nombre de résultats de la requêtes en faisant abstraction de la LIMIT posée.
Dès lors faire les requêtes suivantes ramèneront respectivement les articles désirés (LIMIT) et le nombre total d'article dans la table (sans devoir faire une requête lourde qui compte tous les articles (COUNT(*)) :
SELECT SQL_CALC_FOUND_ROWS `tbl_articles`.`uid` FROM `tbl_articles` LIMIT 10 OFFSET 80; SELECT FOUND_ROWS() AS zend_paginator_row_count;
Hors ligne
Attention ceci n'est valable QUE pour MySQL
le code n'est donc plus portable.
je me posais la question il y a quelque temps sur la couche d'abstraction de ZF.
il serait peut être intéressant d'introduire dans la version future l'accès au caractéristiques du moteur
par exemple dans une classe dérivée de Zend_Db_Table pouvoir faire un test sur le moteur permettrait de mieux optimiser les accès à la base comme celui du SQL_CALC_FOUND_ROWS
par exemple dans le constructeur faire un appel conditionnel pour attacher un Zend_Db_Table_Select Adapté au moteur du coup côté application on a toujours une Zend_Db_Table utilisé comme d'hab mais qui s'appuis sur une Zend_Db_Table_Select optimisé en fonction du moteur. ce qui permet de conserver la probabilité et l'abstraction du moteur tout en proposant des optimisation propre au moteur.
par exemple
SELECT usr_isvalid = 1 AS ISVALID FROM user;
ne fonctionne pas sur tous les moteur SQL (et oui un truc aussi simple)
sur certains il faut écrire
SELECT CASE usr_isvalid WHEN 1 THEN true ELSE false END AS ISVALID FROM user;
en ayant accès dans les classes d'abstraction au caractéristiques du moteur on peut facilement proposer une ou l'autre des requête. du coup il devient facile de rendre le code plus optimal et plus portable.
pour l'heure il faut en passer par les classes de réflexions sur l'adapteur de la base.
A+JYT
Hors ligne
Kaimite a écrit:
Je viens de mettre à jour mon ZF avec la version 1.6 et j'ai testé le Zend_Paginator.
Très simple à mettre en place et à utiliser
Au niveau des requêtes ça ne change pas grand chose :Code:
SELECT COUNT(*) AS zend_paginator_row_count FROM `tbl_articles` SELECT `tbl_articles`.`uid` FROM `tbl_articles` LIMIT 10 OFFSET 80En tout cas c'est très simple à mettre en place !
une petite note au passage puisqu'on parle d'optimisation.
il faut éviter autant que ce peut les *
et particulièrement sur un COUNT. sur un count ça ne sert à rien de compter les élément de toutes les colonnes vu qu'on compte les lignes.
en faisant juste un peu de sémantique on comprends mieux.
SELECT COUNT(*) signifie COMPTER (TOUTE LES COLONNES) pour chaque Ligne
alors que
SELECT COUNT(1) signifie COMPTER (1) pour chaque ligne
Les moteur moderne s'en sortent pas trop mal mais dans leur analyse les moteurs vont avec le * prévoir de remonter toutes les colonnes pour compter les lignes (en général il optimisent après car ils s'aperçoivent que les colonnes ne sont pas utilisées) alors qu'un COUNT(1) ne vas utiliser qu'une seule fois la constante 1 donc pas de remonté de colonne à priori et pas d'optimisation sur les colonnes
si sur les requête simple select count l'impact n'est souvent pas très pertinent il est étonnant de voir le comportement de certain moteur lorsque on place des cout dans des requêtes plus complexes contenant des group by et des sous requêtes.
A+JYT
Hors ligne
Salut,
j'ai vu sur d'autres sites que le count(*) est plus optimise justement.
Voici un article qui explique tout ça.
http://www.mysqlperformanceblog.com/200 … -countcol/
cordialement,
Kaimite
Hors ligne
Effectivement le SQL_CALC_FOUND_ROWS n'est pas générique et implémenter des méthodes d'abstraction dans ce sens serait un nouveau petit plus dans la performance.
Dans l'article relatif à COUNT, il est surtout mis en évidence que faire un COUNT() sur une colonne non-indexée (ou indexée mais couplée) est plus lent qu'un COUNT(*).
Ce que je retiens de cet article (commentaires entre autres) et d'articles connexes, c'est que COUNT(1) est toutefois plus rapide sur la majorité des SGBD car il ne parse pas toutes les colonnes des lignes pour le dénombrement. (et un COUNT() sur une colonne indexée NOT NULL reste mieux qu'un COUNT(*) toutefois).
Dernière modification par Eureka (19-07-2009 16:58:14)
Hors ligne
Pages: 1 2