Bonjour à tous,
Existe il un générateur sérieux PHP de Model en PHP pour Zend_db soit à partir d'un schéma de base existant ou bien d'un XML ?
Si non est ce une idée pertinente d'en écrire un ?
Version imprimable
Bonjour à tous,
Existe il un générateur sérieux PHP de Model en PHP pour Zend_db soit à partir d'un schéma de base existant ou bien d'un XML ?
Si non est ce une idée pertinente d'en écrire un ?
C'est une très bonne question, que je me pose moi même depuis quelques temps. Générer un Model et un Data Mapper est quelque chose de compliqué, qu'il est impossible d'automatiser à 100%.
Pourtant, ça prends énormément de temps à créer initialement avec beaucoup d'éléments répétitifs...
Je ne peux pas t'aider pour ce qui est de savoir si une solution correcte existe pour générer les modèles, je n'ai pas encore cherché, même si à ma connaissance les générateurs se bornent souvent à générer des objets fortement liés à une base de données (principalement des ActiveRecords), et on s'éloigne de ce que je recherche.
Par contre, j'ai hier soir (les grands esprits se rencontrent :aie:) créé un petit prototype de générateur de modèle qui utilise un Zend_Db_Table_Abstract et qui donne rapidement un résultat assez satisfaisant.
Il manque encore (au moins) deux choses fondamentales :
- Externaliser les algorithmes de normalisation des membres du modèle par rapport aux champs de la base. L'externaliser sous forme d'une Stratégie permettrait de plus facilement personnaliser les règles de nommage et de les adapter au cas par cas.
- Externaliser la gestion du typage, car pour ma part un modèle doit être fortement typé et forcer un cast pour les types natifs (int, string, bool...) ou une définition de méthode typée pour les objets dans ses méthodes set*. Je pense qu'il faut l'externaliser car personnellement je fournis les champs de type date d'une base de données dans un objet Zend_Date pour les modèles, ce qui facilite l’interaction application / data layer, mais ça peut ne pas convenir tout le temps, et encore moins à tout le monde (surtout sur le plan des performances).
A mon avis ce genre d'outils n'a d'utilité qu'en création pour gagner un peu de temps : elle implique après coup tellement de réécriture (relation entre modèles, cas où les modèles et les tables ne correspondent pas 1 à 1, nommage à adapter à cause d'une base mal nommée...) qu'une fois le modèle finalisé il ne peut plus "évoluer" grâce à cet outil si la table change, il faudra tout faire à la mano.
Voici le code de la classe, je suis preneur de tout avis bien évidemment :ccool:, mais si l'outil peut être utile (et si la roue n'a pas déjà été inventée ailleurs) ça vaut le coup d'approfondir le concept et d'étendre Zend_Tool pour l'exploiter en ligne de commande.
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150 class ModelGenerator extends Zend_CodeGenerator_Php_Class { /** * * @var Zend_Db_Table_Abstract */ protected $_dbTable; /** * * @var string */ protected $_appNamespace = 'Application'; /** * * @return Zend_Db_Table_Abstract */ public function getDbTable () { return $this->_dbTable; } /** * * @param Zend_Db_Table_Abstract $dbTable * @return Zend_Db_Table_Abstract */ public function setDbTable ($dbTable) { $this->_dbTable = $dbTable; return $this; } /** * * @return string */ public function getAppNamespace () { return $this->_appNamespace; } /** * * @param string $appNamespace * @return ModelGenerator */ public function setAppNamespace ($appNamespace) { $this->_appNamespace = $appNamespace; return $this; } /** * * @return string * @see Zend_CodeGenerator_Php_Class::generate() */ public function generate() { $dbTable = $this->getDbTable(); $appNamespace = $this->getAppNamespace(); if (null !== $dbTable) { $tableInfos = $dbTable->info(); $tableName = $tableInfos['name']; $className = $appNamespace . '_Model_' . $tableName; $this->setName($className); $this->setDocblock(array( 'shortDescription' => "$tableName Model", 'tags' => array( array( 'name' => 'category', 'description' => $appNamespace ), array( 'name' => 'package', 'description' => 'Default' ), array( 'name' => 'subpackage', 'description' => 'Model' ), ) )); foreach ($tableInfos['metadata'] as $name => $infos) { $this->addProperty($name, $infos['DATA_TYPE'], $className); } } return parent::generate(); } public function addProperty($name, $type, $className) { $this->setProperty(array( 'docBlock' => array( 'tags' => array( array( 'name' => 'var', 'description' => $type ) ) ), 'visibility' => 'protected', 'name' => $name )); $this->setMethod(array( 'docBlock' => array( 'tags' => array( array( 'name' => 'return', 'description' => $type ) ) ), 'body' => 'return $this->_' . $name . ';', 'visibility' => 'public', 'name' => 'get' . ucfirst($name) )); $this->setMethod(array( 'docBlock' => array( 'tags' => array( array( 'name' => 'param', 'description' => $type . ' $value' ), array( 'name' => 'return', 'description' => $className ) ) ), 'parameters' => array( array( 'name' => 'value', 'type' => $type ) ), 'body' => '$this->_' . $name . ' = $value;' . "\n" . 'return $this;', 'visibility' => 'public', 'name' => 'set' . ucfirst($name) )); } }
Merci beaucoup pour ta réponse,
Je suis entièrement d'accord et ce fait et celui d'avoir utiliser Hibernate pendant des années qui m'ont amener à cette réflexion. Comme c'est un processus qui est dans tous les ORM java que j'ai utilisé je suis très étonné de ne pas avoir trouvé ceci dans Zend_Db.Citation:
ça prends énormément de temps à créer initialement avec beaucoup d'éléments répétitifs...
Mon souhait est d'avoir quelque chose qu'y se rapproche d'Hibernate dans la génération des objets proxy. Ce type d'outils permet :
- de gagner beaucoup de temps
- de fortement réduire les erreurs par rapport à une écriture manuelle
- de générer sur le même norme tous ses objets du model
Pour Zend_Date je fais pareil. Le but est l’intégration dans Zend Framework il faut pas commencer par quelque chose trop ambitieux.Citation:
Je pense qu'il faut l'externaliser car personnellement je fournis les champs de type date d'une base de données dans un objet Zend_Date pour les modèles, ce qui facilite l’interaction application / data layer, mais ça peut ne pas convenir tout le temps, et encore moins à tout le monde
A mon avis pas complétement si les classes générés sont exploitées seulement en héritage sans jamais y insérer de code manuel ça réduirait ce problème. Je prend pour exemple d'Hibernate. Si la Bdd change il suffit de régénérer le code.Citation:
qu'une fois le modèle finalisé il ne peut plus "évoluer" grâce à cet outil si la table change, il faudra tout faire à la mano.
Si par chance ce ne sont que ajout de colonnes ça passe comme une lettre à la poste.
Si c'est autre chose ça fera toujours du temps de gagner.
[hors sujet]:
Pour l'application je trouve que c'est plus pratique de lancer sous Apache pour faire des rapport Web et debugger et pas en standalone.
A tout hasard, Doctrine ne répondrais pas à tes besoins ? http://www.doctrine-project.org/
C'est une question très "naïve", je n'ai pour ma part pas encore eut le temps de m'y "plonger" pour voir si il permettait de faire ce que je cherche, mais de loin ça ne m'a pas paru être le cas.
Par contre pour le coup, je ne pense pas que Zend_Db puisse être considéré comme un ORM : il fournit "simplement" une interface d'accès à une base de donnée via Zend_Db_Adapter et une implémentation d'un Table Data Gateway
avec Zend_Db_Table, laissant le développeur libre de ses propres choix en terme de mapping.
En effet, par contre je pense qu'effectuer un casting sur les types natifs et typer fortement les autres (Zend_Date...) est un minimum pour l'intérêt de la solution, sans ça il faudrait modifier à la main tous les setters...
Je ne suis pas sûr de te suivre sur ce terrain... Les relations base / modèles ne sont pas toujours du 1 / 1 : il se peut qu'une seule table génère 3 ou 4 modèles sans liens de parenté les uns avec les autres.
Dans ce contexte, ça me paraît dangereux de re-générer les modèles une fois le premier travail de mapping terminé...
Surcharger les modèles systématiquement me paraît aussi assez "dangereux" : explosion du nombre de classes, complexité accrue et... même de perte de temps, au final.
Mais bon, je pense que c'est une question de sensibilité personnelle plus qu'autre chose, et ça ne change pas le besoin de base : générer les modèles...
Même si j'aime bien le "support" CLI, je pense que l'interfaçage Zend_Tool est plus un objectif secondaire qu'une finalité : il ne faut pas empêcher de piloter la création de modèles directement.
J'essaye de bricoler un prototype plus aboutis ce week-end car je vais rapidement avoir besoin d'une solution viable pour divers projets.
J'ai beaucoup hésité entre Doctrine et Zend_DB.Citation:
A tout hasard, Doctrine ne répondrais pas à tes besoins ?
Doctrine est lui un ORM et est plus proche d'hibernate et par conséquent c'est nettement plus proche de que je voudrais. Par contre je n'ai pas trouvé de fonction de retro création à partir d'un schéma existant. Etant donné que je n'ai jamais utilisé doctrine je ne me suis pas étendu fortement en recherche sur le sujet.
Le souci avec Doctrine c'est que dans Zend Framework 1.X n'a pas d' "adapter" pour Doctrine du coup plein de classe de Zend Framework ne peuvent l'utiliser nativement.
Je prend l'exemple de Zend_Paginator il prend en paramètre un Select de Zend_db et pas Doctrine. A priori dans ZF2 ce sera possible (au conditionnel).
C'est mon constat aussi jusqu'ici.
J'ai travaillé un peu sur le sujet, et j'ai désormais un résultat acceptable, bien entendu à éprouver sur des conventions de nommage différentes...
A partir de la table suivante, issue d'un projet perso :
Il me génère le code suivant :Code:
1
2
3
4
5
6
7
8
9
10 CREATE TABLE IF NOT EXISTS `ActivityItem` ( `idActivityItem` INT NOT NULL AUTO_INCREMENT , `titleActivityItem` VARCHAR(255) NOT NULL , `descriptionActivityItem` VARCHAR(255) NULL , `linkActivityItem` VARCHAR(255) NOT NULL , `externalIdActivityItem` VARCHAR(255) NOT NULL , `publicationDateActivityItem` DATETIME NOT NULL , `addedDateActivityItem` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , `idActivitySourceActivityItem` INT NOT NULL );
Comme le projet commence à prendre en envergure (8 classes maintenant) si ça t'intéresse je peux créer un dépôt Github, ça sera plus simple que de mettre des extraits de code source ici.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196 /** * ActivityItem Model * * @category Application * @package Default * @subpackage Model */ class Application_Model_ActivityItem { /** * @var integer */ protected $_id = null; /** * @var string */ protected $_title = null; /** * @var string */ protected $_description = null; /** * @var string */ protected $_link = null; /** * @var string */ protected $_externalId = null; /** * @var Zend_Date */ protected $_publicationDate = null; /** * @var Zend_Date */ protected $_addedDate = null; /** * @var integer */ protected $_idActivitySource = null; /** * @return integer */ public function getId() { return $this->_id; } /** * @param integer $value * @return Application_Model_ActivityItem */ public function setId($value) { $this->_id = (integer) $value; return $this; } /** * @return string */ public function getTitle() { return $this->_title; } /** * @param string $value * @return Application_Model_ActivityItem */ public function setTitle($value) { $this->_title = (string) $value; return $this; } /** * @return string */ public function getDescription() { return $this->_description; } /** * @param string $value * @return Application_Model_ActivityItem */ public function setDescription($value) { $this->_description = (string) $value; return $this; } /** * @return string */ public function getLink() { return $this->_link; } /** * @param string $value * @return Application_Model_ActivityItem */ public function setLink($value) { $this->_link = (string) $value; return $this; } /** * @return string */ public function getExternalId() { return $this->_externalId; } /** * @param string $value * @return Application_Model_ActivityItem */ public function setExternalId($value) { $this->_externalId = (string) $value; return $this; } /** * @return Zend_Date */ public function getPublicationDate() { return $this->_publicationDate; } /** * @param Zend_Date $value * @return Application_Model_ActivityItem */ public function setPublicationDate(Zend_Date $value) { $this->_publicationDate = $value; return $this; } /** * @return Zend_Date */ public function getAddedDate() { return $this->_addedDate; } /** * @param Zend_Date $value * @return Application_Model_ActivityItem */ public function setAddedDate(Zend_Date $value) { $this->_addedDate = $value; return $this; } /** * @return integer */ public function getIdActivitySource() { return $this->_idActivitySource; } /** * @param integer $value * @return Application_Model_ActivityItem */ public function setIdActivitySource($value) { $this->_idActivitySource = (integer) $value; return $this; } }
Merci pour l'exemple.
Oui un dépôt Github ce serait pas mal
j'ai déjà essayé ton code pour générer et ça fonctionne bien.
J'aimerais bien lui ajouter une fonction de Mapping avec une DbTable associé.
Dans mon idée était de commencer par générer toutes les Dbtable de la base.
J'ai fait les test sur Mysql.
J'ai fait une classe SchemaGenerator qui lit un schéma de base et qui génère (via DbTableGeneratorAbstract.php) des fichiers qui hérite de Zend_Db_Table pour chaque table dans la base. Le fichier est NomdeletableAbstract.php.
Ensuite via DbTableGenerator.php si le fichier n'existe pas un fichier prêt à recevoir le code à ajouter est ecrit. Il hérite de la classe Abstract correspondant.
Voir pièce jointe pour le fichier.
La gestion est très light.
ça donne ça pour une table 'table2'
Le generator créée une constant pour chaque nom de colonne dans la table.Code:
1
2
3
4
5
6
7
8
9 -- Base de données: `schematest` -- Structure de la table `table2` CREATE TABLE IF NOT EXISTS `table2` ( `identifiant` int(11) NOT NULL AUTO_INCREMENT, `label` varchar(100) COLLATE utf8_bin NOT NULL, PRIMARY KEY (`identifiant`) )
Ensuite ajout la variable _name et _primary.
Pour _primary il utiliser les constante généré et gére 0 à N clef.
Ensuite la classe d’implémentationCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 <?php /** * table2 Model * * Classe autogenere par DbTableGenerator Date : Sunday 8th of May 2011 04:50:35 AM * * @category Test * @package MonPackage * @subpackage Model */ abstract class Test_Model_table2Abstract extends Zend_Db_Table { /** * Surchage de la propriété parent */ protected $_name = 'table2'; /** * Cette constante est le nom d'une colonne de la table. Le type dans la colonne * est le suivant : int * * @var string */ const COL_identifiant = 'identifiant'; /** * Cette constante est le nom d'une colonne de la table. Le type dans la colonne * est le suivant : varchar * * @var string */ const COL_label = 'label'; /** * Surchage de la propriété parent */ protected $_primary = self::COL_identifiant; } ?>
Est ce que je me suis bien expliqué ?Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 <?php /** * table2 Model * * Classe autogenere par DbTableGenerator Date : Sunday 8th of May 2011 04:50:35 AM * Utilise cette classe ne sera pas re genere ajouter votre code dedans * * @category Test * @package MonPackage * @subpackage Model */ class Test_Model_table2 extends Test_Model_table2Abstract { } ?>
Bonsoir, et merci pour ces exemples. Concernant la génération de DbTable à partir de la base, je ne m'étais pas penché dessus encore car pour moi ça représentait une bien moins grande charge de travail que les Domain Model, mais il n'y a pas de petit profit :ccool:
L'idée de séparer les classes générées des classes finales est intéressante, mais en fait ça me met le doute quant au fait que l'on ait en tête la même architecture.
De mon côté je vois assez peu d'intérêt à rajouter du code personnalisé dans les DbTable : ceux-ci ne servent que d'interface de communication avec la base de données, et tout le code métier se trouvera externalisé dans les Domain Model, tandis que le mapping base / modèle sera géré par les Data Mapper.
J'ai plus l'impression que tu envisages des objets DbTable plus "gros" chargés de récupérer les données et de les mapper, je me trompe ?
Quoi qu'il en soit, j'ai créé le dépôt Github :
https://github.com/lucascorbeaux/Zend_Db-ModelGenerator
J'ai d'ailleurs trouvé des projets similaires sur Github, mais apparemment sans gros suivi. Si tu veux je peux te mettre contributeur si tu as des propositions à faire directement dans le code.
Ca reste un prototype, du coup c'est très légèrement documenté...
Voici un code d'exemple :
Edit : un petit oubli, pour générer des Zend_Db_Table, Zend_Tool le permet déjà mais pas à partir d'une base de données à ma connaissance :Code:
1
2
3
4
5
6
7
8
9 $innerStrategy = new ModelGenerator_NamingStrategy_Default(); $namingStrategy = new ModelGenerator_NamingStrategy_RemoveClassName($innerStrategy); $generator = new ModelGenerator_DomainModel_Generator(array( 'dbTable' => new Application_Model_DbTable_Activity_Item(), 'namingStrategy' => $namingStrategy )); echo $generator->generate();
zf create db-table ClassName table_name
Je voudrais générer le Mapper et les objets basique représentant une ligne d'une table. Faire le cheminement inverse de cette doc.
Avec en plus des constantes pour aider à l'écriture des requêtes.
Dans la limite de la doc que j'ai lu les outils ZF ne permette pas la génération à partir de la table existante.
http://framework.zend.com/manual/fr/...ate-model.html
Désolé pour ma réponse 3 jours après, début de semaine un peu difficile...
En tout cas maintenant je sais qu'on cherche bien une solution au même problème :mrgreen:
En effet, le Zend Framework ne permet pas de générer les tables autrement qu'une par une, par contre ça ne devrait pas être difficile de composer autour :
J'essaye cette semaine (week end inclus...) de finir le prototype en générant les méthodes __get et __set pour le modèle, ainsi que des méthodes toArray et fromArray, ainsi qu'un mapper basique (implémentant find, save, fetchAll et sûrement une méthode plus générique createModel qui génère un model à partir d'un tableau issue d'une requête).Code:
1
2
3
4
5
6 $db = $bootstrap->getResource('db'); $tables = $db->listTables(); // Vérifier si tous les adapters l'implémentent... foreach ($tables as $table) { // Appeler ici le code existant de génération de DbTable }
Pour ma part j'ai implémenté la génération du _metacache (il suffit de faire une dump de la table info)dans la génération ce qui m'a permis de passe de 3sec à 0 sec sur certaines requêtes.
ça c'est plutôt pas mal
J'ai fait la génération des Model Objet Abstract qui appel les Abstracts tables et les implémentation des tables correspondantes mais sans Classe Mapper. Les model objets font leur mapping avec des ROW en utilisant les constantes mais j'ai fait ça vite fait pour gérer une urgence. Je pense qu'il faudrait que repenser une partie de ce point.
En plus j'ai fait l'ajout des TAGS SVN.
Intéressant oui, si on regénère les dbTable à chaque modifications de la base ça peut booster un peu les performances. Par contre, par rapport à un metadata cache performant (APC, memcache...) j'aimerais mesurer les différences concrètes sur un serveur à fort traffic.
De mon côté, j'ai finis un premier prototype :
https://github.com/lucascorbeaux/Zend_Db-ModelGenerator
Très peu (et très mal) testé, mais globalement il arrive à générer dbTable, modèles et mappers simplement en configurant un projet Zend Framework et en exécutant le script generateModels.php.
Il n'arrive pas pour le moment à gérer automatiquement les Zend_Date au niveau du mapper et ne sait pas traiter les clés primaires composites, mais ça reste un prototype.
Pour le moment, je vais lâcher mon clavier et (re)commencer à me poser des questions :
Un outil de génération à usage "ciblé" devrait se faire rapidement, mais ça n'intéressera pas grand monde à part moi ;)
Beaucoup plus compliqué par contre de penser à un outil de génération configurable et réutilisable, ne bloquant pas les utilisateurs pour des applications spécifiques (séparation optionnelles des classes générées abstraites et de leurs implémentations concrètes, conventions de nommage, tags SVN) tout en fournissant une implémentation minimale mais fonctionnelle.
Et d'autres encore, les méthodes fromArray et toArray pourraient par exemple être gérées par une classe parente, et devraient donc ne pas être générées dans les modèles.
Bref, beaucoup de questions à se poser...
C'est pas mal. tu es allé plus loin que moins sur les méthodes et les mappers.
Pour la gestion des dates j'ai du faire une appel à une fonction de traitement qui convertit entre la DB et et ZENd il faut pouvoir appeler une fonction perso selon le format de date utilisé.
J'ai déja commencé à utiliser mon generator et les méthodes fromArray et toArray sont très utile comme par exemple reprendre en direct les values d'un Form. Par contre la manipulation des Zend_DbTable_Row que j'ai faite ne me convient pas à l'usage.
Entièrement d'accord. par exemple j'utilise les conventions de nommage pour générer certain petit plus dans mon code ou le SVN.Citation:
Beaucoup plus compliqué par contre de penser à un outil de génération configurable et réutilisable, ne bloquant pas les utilisateurs pour des applications spécifiques (séparation optionnelles des classes générées abstraites et de leurs implémentations concrètes, conventions de nommage, tags SVN) tout en fournissant une implémentation minimale mais fonctionnelle.
J'ai rendu le code utilisable entre mes différents projets ZF en utilisant des héritages dynamiquement générer mais ça fait beaucoup de niveau d'héritage au final ce qui va à l'encontre du principe de d'avoir un seul descendant.
Bonjour,
Je trouve que c'est intéressant seulement je rencontre quelques difficultés à le faire fonctionner : j'ai d'abord dût mettre les include en dur et lorsque je lance le script il ne me génère que le DbTable avec uniquement le nombre de la table, est-ce normal ?
Pour votre aide,
Par avance,
Merci
Mon code devrait générer 2 classes par Table
une abstract et une autre qui hérite de cette abstract qui doit contenir le code à customisé mais c'est juste une ébauche.
En fait il faut ajouter à ces Dbtable la génération du Model_Object qui représente une ligne de la base et faire le jonction avec les 2.
Sur quel environnement l'avez-vous testé ?
Pour info Doctrine 2 permet de générer une classe entité sur base d'une DB existante : http://www.doctrine-project.org/docs...se-engineering ;)
Ce n'est pas toujours parfait et des fois ça coince, mais il est assez facile d'écrire son propre générateur basique (il restera à retoucher l'entité pour écrire les relations) grâce aux fonctions d'introspection de Doctrine fournies par le SchemaManager que l'on peut obtenir par Doctrine\DBAL\Connection::getSchemaManager().
magnus> Si tu cherches un ORM professionnel du niveau d'hibernate, nul doute que Doctrine 2 est ce qu'il te faut. En plus il n'est pas "ActiveRecord like" comme beaucoup d'autres, il implémente les vrais patterns d'ORM : Data Mapper, Proxy, Unit of work, et compagnie. :)
Il n'est pas encore complètement mûr, mais le sera très bientôt (cf : http://www.doctrine-project.org/docs...wn-issues.html)
Il est utilisable avec ZF1, mais il est clair qu'en ZF2 l'intégration de Doctrine sera plus poussée (notamment avec le paginateur comme tu l'avais souligné).
Merci ovh pour ce retour. En effet, de mon côté on a finalement opté pour Doctrine 2 : les fonctionnalités de génération de métadonnées à partir de la base et d'entités à partir des métadonnées dégrossissent une bonne partie du travail mine de rien, et l'ORM réponds à une énorme partie des besoins sans "trop en faire" non plus.
Mon principal (et pour ainsi dire seul) regret est de ne plus pouvoir utiliser Zend_Db_Select, que je trouve bien plus agréable à utiliser que le QueryBuilder de Doctrine (mais c'est un peu cavalier de comparer les deux, le besoin n'est pas le même).
Ceci dit une problématique ne change pas : ça reste une option uniquement à la création du projet. Une fois que le projet évolue, re-générer les entités ou le SQL est fortement déconseillé.