One hour application - PHP Quebec Conference 2009
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

One hour application - PHP Quebec Conference 2009

on

  • 9,614 views

Making a complete (but simple) application in one hour? I must be made! But with symfony it's possible!

Making a complete (but simple) application in one hour? I must be made! But with symfony it's possible!

Statistics

Views

Total Views
9,614
Views on SlideShare
9,608
Embed Views
6

Actions

Likes
0
Downloads
22
Comments
0

4 Embeds 6

http://www.ph-il.ca 2
http://www.slideshare.net 2
http://www.lmodules.com 1
http://www.linkedin.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution-NonCommercial-NoDerivs LicenseCC Attribution-NonCommercial-NoDerivs LicenseCC Attribution-NonCommercial-NoDerivs License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

One hour application - PHP Quebec Conference 2009 Presentation Transcript

  • 1. One hour application with symfony vendredi 13 novembre 2009 1
  • 2. Aim • Present symfony in an original way • Make an application in one hour vendredi 13 novembre 2009 2
  • 3. Who am I? • Philippe Gamache •PHP security expert at Parler Haut, Interagir Librement •Author of the book « Sécurité PHP 5 et MySQL » with Damien Seguy, at Eyrolles •http://www.ph-il.ca •http://www.phportail.net •http://lapageamelkor.org •naheulbeukauquebec.ca vendredi 13 novembre 2009 3
  • 4. Questions? ? Please wait at the end, we don’t have much time vendredi 13 novembre 2009 4
  • 5. The application • Blog • Comments • Clean URLs vendredi 13 novembre 2009 5
  • 6. Install symfony http://www.symfony-project.org/installation • Source • Sandbox • PEAR • SVN • Linux Package (Debian and SUSE) vendredi 13 novembre 2009 6
  • 7. Install using PEAR pear channel-discover pear.symfony-project.com pear install symfony/symfony-1.2.4 vendredi 13 novembre 2009 7
  • 8. Create the project • Create directory project $ mkdir -p blog $ cd blog • Check symfony’s version $ symfony -V • Create project $ symfony generate:project blog vendredi 13 novembre 2009 8
  • 9. Create the project • Create an application $ symfony generate:app / --escaping-strategy=on / --csrf-secret=Unique$ecr3t1 / frontend • Adjust your web server vendredi 13 novembre 2009 9
  • 10. http://blog.local/frontend_dev.php/ vendredi 13 novembre 2009 10
  • 11. Activating sfDoctrine // config/ProjectConfiguration.class.php public function setup() { $this->enableAllPluginsExcept( array('sfPropelPlugin', 'sfCompat10Plugin')); } vendredi 13 novembre 2009 11
  • 12. The database • Creating the database $ mysqladmin -uroot -pmYsEcret / create blog • Configure the project $ symfony configure:database / --name=doctrine / --class=sfDoctrineDatabase / "mysql:host=localhost;dbname=blog" / root mYsEcret • Clear Propel connection vendredi 13 novembre 2009 12
  • 13. Plugins • Installing plugins http://www.symfony-project.org/plugins/ • sfDoctrineGuardPlugin $ symfony plugin:install / sfDoctrineGuardPlugin / --release=3.0.0 vendredi 13 novembre 2009 13
  • 14. The database diagram vendredi 13 novembre 2009 14
  • 15. The databade model # config/doctrine/schema.yml actAs: [Timestampable] relations: BlogPost: Author: actAs: class: sfGuardUser Timestampable: ~ local: author_id Sluggable: foreign: id fields: [title] type: one BlogComment: unique: true columns: columns: blog_post_id: integer is_published: author_name: type: boolean type: string(255) default: false notnull: true allow_comments: author_email: string(255) type: boolean author_url: string(255) default: true content: author_id: integer(4) type: string(5000) title: notnull: true type: string(255) relations: notnull: true BlogPost: content: local: blog_post_id type: string(500000) foreign: id notnull: true type: one published_at: date foreignAlias: Comments vendredi 13 novembre 2009 15
  • 16. Database fixtures # data/fixtures/fixtures.yml sfGuardUser: 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 vendredi 13 novembre 2009 16
  • 17. Database fixtures BlogPost: 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 ... vendredi 13 novembre 2009 17
  • 18. Database fixtures BlogComment: 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. vendredi 13 novembre 2009 18
  • 19. Create the tables • Create the tables and load all fixtures $ symfony doctrine:build-all-load vendredi 13 novembre 2009 19
  • 20. Creating the code • Use the code generator $ symfony doctrine:generate-crud / --with-show frontend post BlogPost • Delete unnecessary actions • executeNew() • executeEdit() • executeUpdate() • executeDelete() • processForm() vendredi 13 novembre 2009 20
  • 21. Creating the code • Delete unnecessary files • templates/_form.php • templates/editSuccess.php • templates/newSuccess.php • Clear links to other functions vendredi 13 novembre 2009 21
  • 22. Creating the code • Edit 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>By <?php echo $blog_post->getAuthor() ?> on <?php echo $blog_post- >getpublished_at() ?></div> <p> <?php echo $blog_post->getContentSuccess() ?> </p> <p><?php echo link_to('Show more...', '@post_show?slug=' . $blog_post- >getslug()) ?></p> <br /><br /> <?php endforeach; ?> vendredi 13 novembre 2009 22
  • 23. Creating the code • Edit templates/showSuccess.php <h2><?php echo $blog_post->gettitle() ?></h2> <div>By <?php echo $blog_post->getAuthor() ?> on <?php echo $blog_post- >getpublished_at() ?></div> <p><?php echo nl2br($blog_post->getcontent()) ?></p> <hr /><br /><br /> <?php echo link_to('List', '@homepage') ?> vendredi 13 novembre 2009 23
  • 24. Creating the code • Add to templates/layout.php <div id="header"> <h1><?php echo link_to('My blog', '@homepage') ?></h1> </div> <div id="content"> <?php echo $sf_data->getRaw('sf_content') ?> </div> <div id="footer"></div> • Modify web/css/main.css with blog.css vendredi 13 novembre 2009 24
  • 25. Creating the code • Edit 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); } vendredi 13 novembre 2009 25
  • 26. Creating the code • Edit BlogPost.class.php public function getContentSummary() { $out = explode('<', nl2br(substr($this->getcontent(), 0, 500))); return $out[0] . '...'; } • Modify to routing.yml homepage: url: / param: { module: post, action: index } post_show: url: /:slug param: { module: post, action: show } vendredi 13 novembre 2009 26
  • 27. Add comments • Use the code generator $ symfony doctrine:generate-crud / frontend comment BlogComment • Copy the code you’ll need vendredi 13 novembre 2009 27
  • 28. Add comments • Edit code in 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(); } vendredi 13 novembre 2009 28
  • 29. Add comments • Add the code in 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'); } vendredi 13 novembre 2009 29
  • 30. Add comments • Add the code in actions.class.php 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')); } } • Add to routing.yml comment: url: /comment/:slug param: { module: post, action: create } vendredi 13 novembre 2009 30
  • 31. Add comments • Edit 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">Posted on <?php echo $comment->getcreated_at() ?> by <?php echo $comment->getauthor_name() ?> </div> <p> <?php echo $comment->getcontent() ?> </p> </li> <?php endforeach; ?> </ul> <?php endif ?> <br /> ... vendredi 13 novembre 2009 31
  • 32. Add comments • Edit templates/showSuccess.php ... <p class="bold">Add your comment</p> <br /> <?php include_partial('form', array('form' => $form, 'blog_post' => $blog_post)) ?> <hr /><br /><br /> <?php echo link_to('List', '@homepage') ?> vendredi 13 novembre 2009 32
  • 33. Add comments • Edit templates/indexSuccess.php ... <p> <?php echo $blog_post->getContentSummary() ?> </p> <p>Comments (<?php echo count($blog_post->getComments()) ?>) : <?php echo link_to('Show more', '@post_show?slug=' . $blog_post- >getslug()) ?></p> <br /><br /> <?php endforeach; ?> • Move _form.php vendredi 13 novembre 2009 33
  • 34. Add comments • Edit templates/_form.php ... <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> ... • Keep only • author_name • author_email • author_url • content vendredi 13 novembre 2009 34
  • 35. Add comments • Edit 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' => 'Your email ', 'author_name' => 'Your name ', 'author_url' => 'Web site ', 'content' => 'Comment ', )); } vendredi 13 novembre 2009 35
  • 36. Backend creation • Create an application $ symfony generate:app / --escaping-strategy=on / --csrf-secret=UniqueSecret / backend vendredi 13 novembre 2009 36
  • 37. Backend creation • Create modules $ symfony doctrine:generate-admin / --module=post backend BlogPost $ symfony doctrine:generate-admin / --module=comment backend / BlogComment vendredi 13 novembre 2009 37
  • 38. Backend creation • Edit routing.yml sf_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 rules homepage: url: / param: { module: post, action: index } vendredi 13 novembre 2009 38
  • 39. Backend creation • Add to templates/layout.php <div id="header"> <h1><?php echo link_to('My blog', '@homepage') ?></h1> </div> <div id="menu"> <ul> <li><?php echo link_to('Posts', '@blog_post_post') ?></li> <li><?php echo link_to('Comments', '@blog_comment_comment') ?></li> </ul> </div> <div id="content"> <?php echo $sf_data->getRaw('sf_content') ?> </div> <div id="footer"></div> • Edit apps/frontend/config/view.yml vendredi 13 novembre 2009 39
  • 40. Backend creation • Edit setting.yml ... all: .actions: login_module: sfGuardAuth login_action: signin secure_module: sfGuardAuth secure_action: secure .settings: enabled_modules: [default, sfGuardAuth] ... • Edit security.yml default: is_secure: on vendredi 13 novembre 2009 40
  • 41. Backend creation • Edit post generator.yml ... config: actions: ~ fields: ~ list: title: Message list display: [is_published, author_id, =title, published_at] filter: display: [is_published] form: ~ edit: title: Edit post : "%%title%%" display: [is_published, author_id, title, content, published_at] new: title: New post display: [is_published, author_id, title, content, published_at] vendredi 13 novembre 2009 41
  • 42. Backend creation • Edit comment generator.yml ... config: actions: ~ _delete: ~ _list: ~ fields: ContentSummary: label: Comments list: object_actions: _delete: ~ actions: __: ~ title: Comments list display: [blog_post_id, =author_name, =ContentSummary] filter: display: [blog_post_id] form: ~ edit: ~ new: ~ vendredi 13 novembre 2009 42
  • 43. Backend creation • Edit myUser.class.php class myUser extends sfGuardSecurityUser { } vendredi 13 novembre 2009 43
  • 44. To go further • Add tags • Add a mini-calendar • Display posts per month • Add search • Add feeds (RSS, ATOM) via sfFeed2plugins vendredi 13 novembre 2009 44
  • 45. Questions? philippe.gamache@symfony-project.com info@ph-il.ca http://www.symfoy-project.org http://www.phportail.net vendredi 13 novembre 2009 45
  • 46. vendredi 13 novembre 2009 46