une application en deux heure - php québec janvier 2009
DESCRIPTION
Faire une application complète (mais simple) en deux heures? Je dois être fou! Mais avec symfony, c'est possible!TRANSCRIPT
Une application en deux heures
Avec Symfony
1vendredi 13 novembre 2009
Objectif
• Présenter symfony d’une façon originale
• Faire une application en une heure
2vendredi 13 novembre 2009
Qui suis-je?
•Philippe Gamache
•Expert en sécurité PHP chez Sensio Labs
•Auteur du livre « Sécurité PHP 5 et MySQL » avec Damien Seguy, chez Eyrolles
•http://www.phportail.net•http://lapageamelkor.org•naheulbeukauquebec.ca
3vendredi 13 novembre 2009
Des questions?
N’attendez pas à la fin ?
4vendredi 13 novembre 2009
L’application
• Blogue
• Commentaires
• URLs propres
5vendredi 13 novembre 2009
symfony
• Cadre d’application WEB en PHP
• Basé sur :• 10 ans d’expérience chez Sensio
• D’autres logiciels libres existants
• Licence MIT
• Documentation est libre
• Grande communauté
6vendredi 13 novembre 2009
symfony
• Créer pour:
• Sites web professionnels
• Besoins complexes
• Environnements exigeants
• Développement rapide
7vendredi 13 novembre 2009
Installer symfony
• Source
• Bac à sable
• Installation via PEAR
• Installation via SVN
• Installation Linux (Debian et SUSE)
http://www.symfony-project.org/installation
8vendredi 13 novembre 2009
Installation PEAR
pear channel-discover pear.symfony-project.com
pear install symfony/symfony-1.2.1
9vendredi 13 novembre 2009
Création du projet
• Créer le répertoire du projet
• Vérifier la version de symfony
• Créer un projet
$ mkdir -p blogue$ cd blogue
$ symfony -V
$ symfony generate:project blogue
10vendredi 13 novembre 2009
Création du projet
• Créer une application
• Ajuster votre serveur web
$ symfony generate:app / --escaping-strategy=on / --csrf-secret=UniqueSecret / frontend
11vendredi 13 novembre 2009
http://blogue.local/frontend_dev.php/
12vendredi 13 novembre 2009
Activation de sfDoctrine
// config/ProjectConfiguration.class.phppublic function setup(){ $this->enableAllPluginsExcept( array('sfPropelPlugin', 'sfCompat10Plugin'));}
13vendredi 13 novembre 2009
La base de données
• Créer la base de données
• Configurer le projet
• Effacer la connexion de Propel
$ symfony configure:database / --name=doctrine / --class=sfDoctrineDatabase / "mysql:host=localhost;dbname=blogue" / root mYsEcret
$ mysqladmin -uroot -pmYsEcret / create jobeet
14vendredi 13 novembre 2009
Plugiciels
• Installer les plugiciels
• sfDoctrineGuardPluginhttp://www.symfony-project.org/plugins/
$ symfony plugin:install / sfDoctrineGuardPlugin / --release=3.0.0
15vendredi 13 novembre 2009
Le modèle
16vendredi 13 novembre 2009
Le schéma # config/doctrine/schema.ymlactAs: [Timestampable]
BlogPost: actAs: Timestampable: ~ Sluggable: fields: [title] unique: true columns: is_published: type: boolean default: false allow_comments: type: boolean default: true author_id: integer(4) title: string(255) content: string(500000) published_at: date relations: Author: class: sfGuardUser local: author_id foreign: id type: one
BlogComment: columns: blog_post_id: integer author_name: string(255) author_email: string(255) author_url: string(255) content: string(5000) relations: BlogPost: local: blog_post_id foreign: id type: one foreignAlias: Comments
17vendredi 13 novembre 2009
Données de tests# data/fixtures/fixtures.ymlsfGuardUser: philippeg: username: Philippe Gamache password: password is_super_admin: true
sfGuardPermission: sgp_admin: name: admin description: Administrator permission
sfGuardGroup: sgg_admin: name: admin description: Administrator group
sfGuardGroupPermission: sggp_admin: sfGuardGroup: sgg_admin sfGuardPermission: sgp_admin
sfGuardUserGroup: sgug_admin: sfGuardGroup: sgg_admin sfGuardUser: philippeg
18vendredi 13 novembre 2009
Données de testsBlogPost: post_1: Author: philippeg title: Lorem ipsum dolor sit amet content: | <p>Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut...</p> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do...</p> is_published: true published_at: 09-01-07 post_2: Author: philippeg title: Ut enim ad minim veniam content: | <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris...</p> <p>Duis aute irure dolor in reprehenderit in voluptate velit esse...</p> is_published: true published_at: 09-01-07 post_3: Author: philippeg title: Duis aute irure dolor in reprehenderit in voluptate content: | <p>Duis aute irure dolor in reprehenderit in voluptate velit esse...</p> <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris...</p> is_published: true published_at: 09-01-07...
19vendredi 13 novembre 2009
Données de testsBlogComment: comment_1: BlogPost: post_1 author_name: lorem content: Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. comment_2: BlogPost: post_1 author_name: elit content: Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. comment_3: BlogPost: post_3 author_name: aute content: Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. comment_4: BlogPost: post_3 author_name: aute content: ESunt in culpa qui officia deserunt mollit anim id est laborum.
20vendredi 13 novembre 2009
Création du code
• Utiliser le générateur de code
• Effacer les actions inutiles
• executeNew()• executeEdit()• executeUpdate()• executeDelete()• processForm()
$ symfony doctrine:generate-crud / --with-show frontend post BlogPost
21vendredi 13 novembre 2009
Création du code
• Effacer les fichiers inutiles
• templates/_form.php• templates/editSuccess.php• templates/newSuccess.php
• Effacer les liens vers les autres fonctions
22vendredi 13 novembre 2009
Création du code
• Modifier templates/indexSuccess.php<?php foreach ($blog_post_list as $blog_post): ?> <h2><?php echo link_to($blog_post->gettitle(), '@post_show?slug=' . $blog_post->getslug()) ?></h2> <div>Par <?php echo $blog_post->getAuthor() ?> le <?php echo $blog_post->getpublished_at() ?></div> <p> <?php echo $blog_post->getContentSuccess() ?> </p> <p><?php echo link_to('Voir plus...', '@post_show?slug=' . $blog_post->getslug()) ?></p> <br /><br /><?php endforeach; ?>
23vendredi 13 novembre 2009
Création du code
• Modifier templates/showSuccess.php<h2><?php echo $blog_post->gettitle() ?></h2><div>Par <?php echo $blog_post->getAuthor() ?> le <?php echo $blog_post->getpublished_at() ?></div>
<p><?php echo nl2br($blog_post->getcontent()) ?></p>
<hr /><br /><br />
<?php echo link_to('List', '@homepage') ?>
24vendredi 13 novembre 2009
Création du code
• Ajouter au templates/layout.php
• Ajouter web/css/blog.css
• Modifier apps/frontend/config/view.yml
<div id="header"> <h1><?php echo link_to('Mon Blogue', '@homepage') ?></h1></div>
<div id="content"> <?php echo $sf_data->getRaw('sf_content') ?></div><div id="footer"></div>
25vendredi 13 novembre 2009
Création du code
• Modifier actions.class.php public function executeIndex(sfWebRequest $request) { $this->blog_post_list = Doctrine::getTable('BlogPost') ->createQuery('a') ->where('a.is_published = 1') ->execute(); }
public function executeShow(sfWebRequest $request) { $this->blog_post = Doctrine::getTable('BlogPost') ->findOneBySlug($request->getParameter('slug')); $this->forward404Unless($this->blog_post); }
26vendredi 13 novembre 2009
Création du code
• Modifier BlogPost.class.php
• Ajouter à routing.yml
public function getContentSummary() { $out = explode('<', nl2br(substr($this->getcontent(), 0, 500))); return $out[0] . '...'; }
post_show: url: /:slug param: { module: post, action: show }
27vendredi 13 novembre 2009
Ajouter les commentaires
• Utiliser le générateur de code
• Copier le code dont vous aurez besoin
$ symfony doctrine:generate-crud / frontend comment BlogComment
28vendredi 13 novembre 2009
Ajouter les commentaires
• Modifier le code dans actions.class.php public function executeIndex(sfWebRequest $request) { $this->blog_post_list = Doctrine::getTable('BlogPost') ->createQuery('p') ->groupBy('p.published_at, p.id') ->where('p.is_published = 1') ->execute(); }
public function executeShow(sfWebRequest $request) { $this->blog_post = Doctrine::getTable('BlogPost') ->findOneBySlug($request->getParameter('slug')); $this->forward404Unless($this->blog_post);
$this->form = new BlogCommentForm(); }
29vendredi 13 novembre 2009
Ajouter les commentaires
• Ajouter le code dans actions.class.php public function executeCreate(sfWebRequest $request) { $this->forward404Unless($request->isMethod('post')); $this->blog_post = Doctrine::getTable('BlogPost') ->findOneBySlug($request->getParameter('slug')); $this->forward404Unless($this->blog_post);
$comment = new BlogComment(); $comment->setBlogPost($this->blog_post);
$this->form = new BlogCommentForm($comment); $this->processForm($request, $this->form);
$this->setTemplate('show'); }
30vendredi 13 novembre 2009
Ajouter les commentaires
• Ajouter le code dans actions.class.php
• Ajouter a routing.yml
public function processForm(sfWebRequest $request, sfForm $form) { $form->bind($request->getParameter($form->getName())); if ($form->isValid()) { $blog_comment = $form->save(); $this->redirect('@post_show?slug=' . $request->getParameter('slug')); } }
comment: url: /comment/:slug param: { module: post, action: create }
31vendredi 13 novembre 2009
Ajouter les commentaires
• Modifier templates/showSuccess.php...<p><?php echo nl2br($blog_post->getcontent()) ?></p><?php if (count($blog_post->getComments())): ?> <ul id="comments"> <?php foreach ($blog_post->getComments() as $comment): ?> <li class="comments"> <br /> <div class="bold">Poster <?php echo $comment->getcreated_at() ?> par <?php echo $comment->getauthor_name() ?> le </div> <p> <?php echo $comment->getcontent() ?> </p> </li> <?php endforeach; ?> </ul><?php endif ?><br />...
32vendredi 13 novembre 2009
Ajouter les commentaires
• Modifier templates/showSuccess.php...
<p class="bold">Ajouter votre commentaire</p><br /><?php include_partial('form', array('form' => $form, 'blog_post' => $blog_post)) ?><hr /><br /><br />
<?php echo link_to('List', '@homepage') ?>
33vendredi 13 novembre 2009
Ajouter les commentaires
• Modifier templates/indexSuccess.php
• Déplacer _form.php
... <p> <?php echo $blog_post->getContentSuccess() ?> </p> <p>Commentaire (<?php echo count($blog_post->getComments()) ?>) : <?php echo link_to('Voir plus...', '@post_show?slug=' . $blog_post->getslug()) ?></p> <br /><br /><?php endforeach; ?>
34vendredi 13 novembre 2009
Ajouter les commentaires
• Modifier templates/_form.php
• Garder que • author_name• author_email• author_url• content
...<form action="<?php echo url_for('@comment?slug=' . $blog_post->getSlug()) ?>" method="POST"><?php if (!$form->getObject()->isNew()): ?><input type="hidden" name="sf_method" value="PUT" /><?php endif; ?> <table>...
35vendredi 13 novembre 2009
Ajouter les commentaires
• Modifier BlogCommentForm.class.php public function configure() { unset( $this['created_at'], $this['updated_at'], $this['blog_post_id'] ); $this->validatorSchema['author_email'] = new sfValidatorEmail(array('required' => false)); $this->validatorSchema['author_url'] = new sfValidatorUrl(array('required' => false)); $this->widgetSchema->setLabels(array( 'author_email' => 'Votre courriel ', 'author_name' => 'Votre nom ', 'author_url' => 'Site Web ', 'content' => 'Commentaire ', )); }
36vendredi 13 novembre 2009
Création du Backend
• Créer une application$ symfony generate:app / --escaping-strategy=on / --csrf-secret=UniqueSecret / backend
37vendredi 13 novembre 2009
Création du Backend
• Créer les modules$ symfony generate:admin / --module=post backend BlogPost$ symfony generate:admin / --module=comment backend / BlogComment
38vendredi 13 novembre 2009
Création du Backend
• Modifier routing.ymlsf_guard_signin: url: /login param: { module: sfGuardAuth, action: signin }
sf_guard_signout: url: /logout param: { module: sfGuardAuth, action: signout }
sf_guard_password: url: /request_password param: { module: sfGuardAuth, action: password }
# default ruleshomepage: url: / param: { module: post, action: index }
39vendredi 13 novembre 2009
Création du Backend
• Ajouter au templates/layout.php
• Modifier apps/frontend/config/view.yml
<div id="header"> <h1><?php echo link_to('Mon Blogue', '@homepage') ?></h1></div>
<div id="menu"> <ul> <li><?php echo link_to('Poste', '@blog_post') ?></li> <li><?php echo link_to('Commentaire', '@blog_comment') ?></li> </ul></div>
<div id="content"> <?php echo $sf_data->getRaw('sf_content') ?></div>
<div id="footer"></div>
40vendredi 13 novembre 2009
Création du Backend
• Modifier setting.yml
• Modifier setting.yml
...all: .actions: login_module: sfGuardAuth login_action: signin
secure_module: sfGuardAuth secure_action: secure .settings: enabled_modules: [default, sfGuardAuth]...
default: is_secure: on
41vendredi 13 novembre 2009
Création du Backend
• Modifier post generator.yml... config: actions: ~ fields: ~ list: title: Liste de message display: [is_published, author_id, =title, published_at] filter: display: [is_published] form: ~ edit: title: Modifier le message "%%title%%" display: [is_published, author_id, title, content, published_at] new: title: Nouveau message display: [is_published, author_id, title, content, published_at]
42vendredi 13 novembre 2009
Création du Backend
• Modifier comment generator.yml... config: actions: ~ _delete: ~ _list: ~ fields: ContentSummary: label: Commentaires list: object_actions: _delete: ~ actions: __: ~ title: Liste des commentaires display: [blog_post_id, =author_name, =ContentSummary] filter: display: [blog_post_id] form: ~ edit: ~ new: ~
43vendredi 13 novembre 2009
Création du Backend
• Modifier myUser.class.phpclass myUser extends sfGuardSecurityUser{}
44vendredi 13 novembre 2009
Pour aller plus loins
• Ajouter étiquettes (tags)
• Ajouter un mini-calendrier
• Mettre les billets par mois
• Ajouter recherche par date
• Ajouter des flux de données (RSS, ATOM) via sfFeed2plugins
45vendredi 13 novembre 2009
Questions?
[email protected]@ph-il.ca
http://www.symfoy-project.orghttp://www.phportail.net
46vendredi 13 novembre 2009
47vendredi 13 novembre 2009