560 likes | 740 Views
symfony. generators. contexte. Répétition de l’implémentation des méthodes CRUD pour ls objets métier Commande symfony permettant d’initialiser un module symfony <TASK_NAME> <APP_NAME> <MODULE_NAME> <CLASS_NAME> <TASK_NAME> propel-init-crud propel-generate-crud propel-init-admin.
E N D
symfony generators
contexte • Répétition de l’implémentation des méthodes CRUD pour ls objets métier • Commande symfony permettant d’initialiser un module symfony <TASK_NAME> <APP_NAME> <MODULE_NAME> <CLASS_NAME> • <TASK_NAME> • propel-init-crud • propel-generate-crud • propel-init-admin.
Scaffolding • un scaffolding est une structure basique (actions et templates) utilisée pour implémenter les méthodes CRUD sur une table • Le code est minimal car il est censé servir de guide pour une développement future • C’est une base qui doit être adaptée pour correspondre aux besoin logiques et de présentation du développeur. • Les scaffoldings sont utilisés essentiellement pendant la phase de développement, pour avoir un accès web a une base de données, pour construire un prototype, ou comme base pour un module basé lui-même sur une table
Administration • Une administration est une interface sophistiquée de manipulation de données, typiquement dédiée à la partie back office • Les Administrations se distinguent des scaffolding en cela que leur code n’est pas modifiable. • Elles peuvent être paramétrées, étendue, ou assemblées par héritage ou configuration. • Leur présentation est importante, et elles offrent des possibilités de tri, pagination, et filtrage. • Une administration peut être créée et distribuée au client comme une partie finie de l’application
Terminologie symfony • Scaffolding (crud) • inheritance (init) • Classes vides (squelettes) • N’est pas fait pour être modifié ( phpMyAdmin) • code generation (generate) • Classes avec Code • En vue d’une adpatation du code généré • Administration (admin) • Modifiable via la configuration
Initialiser un scaffolding • symfony propel-init-crud myapp article Article • http://localhost/myapp_dev.php/article • Aucune action dans actions.class.php • Aucun template dans le répertoire templates/ • Tout est hérité d’une classe auto-générée • myproject/cache/myapp/prod/module/autoArticle/ • en cache
Générer un scaffolding • symfony propel-generate-crud myapp article Article • http://localhost/myapp_dev.php/article • Contrôleur et templates générés à partir du schema.yml dans myapp/modules/article/ • Code pour CRUD
Détails de la génération d’un scaffolding • Dans actions/actions.class.php • index : redirection sur l’action list • list : affiche la liste de tous les enregistrements de la table • show : affiche toutes les colonnes d’un enregistrement • edit : affiche un formulaire de modification d’un enregistrement • update : action appelée par le formulaire d’édition • delete : supprimer un enregistrment • create : ajouter un nouvel enregistrement • Dans le répertoire templates/ • editSuccess.php : formulaire d’édition d’un enregistrement • listSuccess.php : liste de tous les enregistrements • showSuccess.php : détails d’un enregistrement
actions.class.php généré class articleActions extends sfActions { public function executeIndex() { return $this->forward('article', 'list'); } public function executeList() { $this->articles = ArticlePeer::doSelect(new Criteria()); } public function executeShow() { $this->article = ArticlePeer::retrieveByPk($this->getRequestParameter('id')); $this->forward404Unless($this->article); } ...
administration • Typiquement adapté au back office • symfony init-app backend • symfony propel-init-admin backend article Article • http://localhost/backend.php/article • Fichier de conf cutomisable generator.yml • Omposants logiques • Look & feel • Possibilité de refédinir les action ste les templates
administration – code généré • Tout est en cache • dans actions/actions.class.php • create : redirection vers l’action edit • delete : supprime un enregistrement • edit : affiche le formulaire d’édition d’un module, et assure le traitement de la soumission de ce formulaire • index : redirige vers l’action list • list : affiche la liste de tous les enregistrements • save : redirige vers l’action edit • Dans le répertoire templates/ • editSuccess.php : _edit_actions.php, _edit_footer.php, _edit_form.php, _edit_header.php, _edit_messages.php • _filters.php • listSuccess.php : _list.php, _list_actions.php, _list_footer.php, _list_header.php, _list_messages.php, _list_td_actions.php, _list_td_stacked.php, _list_td_tabular.php, _list_th_stacked.php, _list_th_tabular.php
generator.yml • backend/modules/article/config/generator.yml par défaut • N.B. toute customisation se fait à la suite du thème et doit par conséquent commencer par 4 espaces http://www.symfony-project.org/uploads/assets/sfAdminGeneratorRefCard.pdf generator: class: sfPropelAdminGenerator param: model_class: Article theme: default
generator.yml - action list - typique generator: class: sfPropelAdminGenerator param: model_class: Article theme: default fields: author_id: { name: Article author } list: title: List of all articles display: [title, author_id, category_id] fields: published_on: { params: date_format='dd/MM/yy' } layout: stacked params: | %%is_published%%<strong>%%=title%%</strong><br /> <em>by %%author%% in %%category%% (%%published_on%%)</em> <p>%%content_summary%%</p> filters: [title, category_id, author_id, is_published] max_per_page: 2
generator.yml - action edit - typique generator: class: sfPropelAdminGenerator param: model_class: Article theme: default fields: author_id: { name: Article author } edit: title: Editing article "%%title%%" display: "Post": [title, category_id, content] "Workflow": [author_id, is_published, created_on] fields: category_id: { params: disabled=true } is_published: { type: plain} created_on: { type: plain, params: date_format='dd/MM/yy' } author_id: { params: size=5 include_custom=>> Choose an author << } published_on: { credentials: } content: { params: rich=true tinymce_options=height:150 }
generator.yml - fields • Par défaut la liste des champs est déduite du schema.yml • Il est possible de paramétrer quels champs seront affichés, cachés, et même d’afficher des champs customiser n’ayant pas une correspondance direct avec l’objet • Fields peut agir au niveau général et peut être redéfini au niveau de l’action edit ou list (c’est un principe général)
generator.yml – fields configuration • name: nom de l’objet • type: type de balise d’édition (de formulaire) à utiliser • params: paramètres supplémentaires: classes CSS, taille de la balise d’édition, etc … • help: texte d’aide afficher lors de l’édition
generator.yml - display • Permet de spécifier quels champs sont affichés dans une action ainsi que l’ordre d’affichage (edit & list) • Permet également de regrouper les champs par rubrique (edit) generator: class: sfPropelAdminGenerator param: model_class: Comment theme: default list: display: [id, article_id, content] edit: display: NONE: [article_id] Editable: [author, content, created_at]
generator.yml – display II • Par défaut les clés primaires sont toujours cachées
generator.yml – customized fields • Les champs du generator.yml ne doivent pas forcément correspondre à des champs de base de données • Un getter du modèle peut être utilisé dans l’action list • Un getter et / ou un setter peut être utilisé dans l’action list et edit
generator.yml – customized fields II • lib/model/Article.php public function getNbComments() { return $this->countComments(); } generator: class: sfPropelAdminGenerator param: model_class: Article theme: default list: display: [id, title, nb_comments, created_at]
generator.yml – customized fields III • lib/model/Comment.class.php public function getArticleLink() { return link_to($this->getArticle()->getTitle(), 'article/edit?id='.$this->getArticleId()); } generator: class: sfPropelAdminGenerator param: model_class: Comment theme: default list: display: [id, article_link, content]
generator.yml - partial • MVC compliance!! • modules/comment/templates/_article_link.php <?php echo link_to($comment->getArticle()->getTitle(), 'article/edit?id='.$comment->getArticleId()) ?> • Accès à l’objet courant • currentObject -> $current_object list: display: [id, _article_link, created_at] fields: article_link: { name: Article }
generator.yml partial + logic = component • Appel à la méthode articleLink de actions/components.class.php • Peut être utilisée dans le contexte list, edit, filter • Le contexte est accessible via $type list: display: [id, ~article_link, created_at] fields: article_link: { name: Article }
Paramétrage de l’affichagele titre list: title: List of Articles ... edit: title: Body of article %%title%% display: [content] %% … %% Permet d’accéder à un champs de l’objet
generator.yml - note d’aide modules/comment/config/generator.yml edit: fields: ... article_id: { help: The current comment relates to this article }
generator.yml – format de date • N.B. le administrations sont i18n - ready list: fields: created_at: { name: Published, params: date_format='dd/MM' }
generator.yml – affichage de l’action list • Par défaut l’éction edit est lié (au sens hypertexte) à la clé primaire • = devant le nom du champs cliquable list: display: [article_link, =content]
generator.ymltabular (default)/ stacked list: layout: stacked params: | %%=content%% <br /> (sent by %%author%% on %%created_at%% about %%article_link%%) display: [created_at, author, content]
generator.yml - filtres list: filters: [article_id, author, created_at] layout: stacked params: | %%=content%% <br /> (sent by %%author%% on %%created_at%% about %%article_link%%) display: [created_at, author, content]
generator.yml – filtres II • Pour les colonnes textes le filtre est une entrée texte possédant (*) en caractère joker • Pour les clé étrangères le filtre est une liste déroulante contenant les enregistrements de la table liée (comme pour object_select_tag(), le texte des options est celui retourné par la méthode __toString() de la classe liée) • Pour les colonnes dates le filtre est composé de deux calendrier (rich) permettant la sélection d’un intervalle de temps • Pour les colonnes booléennes, le filtre est une liste déroulante possédant les valeurs: « true », « false », et « true or false » - la dernière valeur réinitialise le filtre
generator.yml – filtres partial • Imaginons un champs status pouvant prendre deux valeurs (open ou closed), sans table étrangère • templates/_state.php <?php echo select_tag('filters[state]', options_for_select(array( '' => '', 'open' => 'open', 'closed' => 'closed', ), isset($filters['state']) ? $filters['state'] : '‘ )) ?> • config/generator.yml list: filters: [date, _state] • N.B. le contenu des champs est accessible via $filter
generator.yml – filtrage par valeur vide • Afficher tous les commentaires sans auteur list: fields: author: { filter_is_empty: true } filters: [article_id, author, created_at]
generator.yml – trier les listes • En liste toutes les colonnes sont cliquables pour l’ordonnancement • Lien direct vers une liste ordonnée selon une colonne <?php echo link_to('Comment list by date', 'comment/list?sort=created_at&type=desc' ) ?> • Les champs partial ne peuvent pas être un critère de tri list: sort: created_at # Alternative syntax, to specify a sort order sort: [created_at, desc]
generator.yml - pagination list: max_per_page: 5
generator.yml – utiliser un jointure pour accélerer les temps de réponse • Par défaut doSelect est utilisé • Affichage du nom de l’auteur d’un commentaire • requête supplémentaire à chaque commentaire list: peer_method: doSelectJoinArticle
generator.yml – changer le type d’un champs en édition • Une colonne définie comme integer, float, char, varchar(size) sera représentée en édition par object_input_tag(). • Une colonne définie comme longvarchar sera représentée en édition object_textarea_tag(). • Une clé étrangère sera reprsentée par object_select_tag(). • Une colonne définie comme boolean sera représentée par object_checkbox_tag(). • Une colonne définie comme timestamp ou date sera représentée object_input_date_tag().
generator.yml – changer le type d’un champs en édition II edit: fields: ## Drop the input, just display plain text id: { type: plain } ## The input is not editable author: { params: disabled=true } ## The input is a textarea (object_textarea_tag) content: type: textarea_tag params: rich=true css=user.css tinymce_options=width:330 ## The input is a select (object_select_tag) article_id: { params: include_custom=Choose an article } <?php echo object_select_tag($comment, 'getArticleId', 'related_class=Article', 'include_custom=Choose an article') ?>
generator.yml – gérer les champs partial • templates/_newpassword.php <?php echo input_password_tag('newpassword', '') ?> edit: display: [id, nickname, _newpassword] fields: newpassword: name: Password help: Enter a password to change it
generator.yml – gérer les champs partial II class userActions extends autouserActions { protected function updateUserFromRequest() { $password = $this->getRequestParameter('newpassword'); if ($password) { $this->user->setPassword($password); } parent::updateUserFromRequest(); } }
generator.yml – gérer les champs partial III • Imaginons que newpassword soit un champs de la table • templates/_newpassword.php <?php echo input_password_tag(‘user[newpassword]', '') ?> • Rien à redéfinit dans le contôleur • Pour accéder à la valeur dans le contrôleur $user = $this->getRequestParameter(‘user'); $password = $user['newpassword‘];
generator.yml – relation 1-n • Génération automatique de liste déroulante • La valeur est toujours l’id • Le texte est le résultat de la méthode __toString() de l’objet lié ou l’id si cette méthode n’existe pas • relation n-1 : nombre de commentaires liés à un article • Gestion via un partial
generator.yml – relation n-n edit: fields: article_author: { type: admin_double_list, params: through_class=ArticleAuthor }
generator.yml – actions de base list: title: List of Articles object_actions: _edit: ~ _delete: ~ actions: _create: ~ edit: title: Body of article %%title%% actions: _list: ~ _save: ~ _save_and_add: ~ _delete: ~
generator.yml – ajouter une action list: title: List of Articles object_actions: _edit: - _delete: - addcomment: { name: Add comment, action: addComment, icon: addcomment.png } • Article/actions.actions.class.php public function executeAddComment() { $comment = new Comment(); $comment->setArticleId($this->getRequestParameter('id')); $comment->save(); $this->redirect('comment/edit?id='.$comment->getId()); }
generator.yml – supprimer les actions • Pour supprimer toutes les actions d’une section list: title: List of Articles actions: {}
generator.yml - nommage • Convention de nommage dans les administrations • champs de formulaire pour $article->title • name=‘’article[title]’’ • id=‘’article_title’’ // generator.yml edit: display: [title] // Resulting _edit_form.php template <?php echo object_input_tag($article, 'getTitle', array('control_name' => 'article[title]')) ?> // Resulting HTML <input type="text" name="article[title]" id="article_title" value="My Title" />
generator.yml – conséquence sur les validateurs ## Replace square brackets by curly brackets in the fields list fields: article{title}: required: msg: You must provide a title ## For validator parameters, use the original field name between quotes sfCompareValidator: check: "user[newpassword]" compare_error: The passwords don’’t
generator.yml - credentials ## The id column is displayed only for users with the admin credential list: title: List of Articles layout: tabular display: [id, =title, content, nb_comments] fields: id: { credentials: [admin] } ## The addcomment interaction is restricted to the users with the admin credential list: title: List of Articles object_actions: _edit: - _delete: - addcomment: credentials: [admin] name: Add a comment action: addComment icon: backend/addcomment.png
generator.yml – feuille de style generator: class: sfPropelAdminGenerator param: model_class: Comment theme: default css: mystylesheet