Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Speed up your developments with Symfony2

  • Login to see the comments

Speed up your developments with Symfony2

  1. 1. Speed Up YourDevelopmentswith Symfony2<br />
  2. 2.
  3. 3. Hugo Hamon<br />Trainings Manager<br />hhamon on Twitter<br />International speaker<br />
  4. 4. Builtaroundstandalone and decoupled components…<br />
  5. 5. … and a full-stackframeworkbased on those components<br />
  6. 6. Application bundles<br />Third party bundles<br />The Symfony2 stack<br />Bridges<br />Third party libraries<br />Core Bundles<br />Standalone Components<br />
  7. 7. « A Bundleis a directory that has a well-defined structure and can host anythingfrom classes to controllers and web resources.  »<br />
  8. 8. Whatmakes Symfony2 unique?<br />
  9. 9. Symfony2 follows standards <br />& best practices<br /><ul><li>RFC2616
  10. 10. PHPUnit
  11. 11. Jinja Templates
  12. 12. Design Patterns</li></li></ul><li>Symfonyisnoweasier<br />to install and configure<br />http://symfony.com/download<br />
  13. 13. Several distributions available<br />Download the Standard Edition that hosts the framework, standard bundles and a default application architecture.<br />
  14. 14. Easy installation and configuration<br />
  15. 15. Web configuration<br />Configure the databaseaccessparameters<br />
  16. 16. Start to use Symfony2and happy coding<br />
  17. 17. Want to giveit a try?<br />
  18. 18. Symfony2 Philosophy<br />« Basically, Symfony2 asksyou to convert a Requestinto a Response »<br />
  19. 19. Request Handling<br />classDefaultControllerextends Controller<br />{<br />/**<br /> * @Route("/hello/{name}")<br /> */<br />public functionindexAction($name)<br /> {<br />// ... do things<br />returnnewResponse(sprintf('Hello %s!', $name));<br /> }<br />}<br />
  20. 20. RequestHandling<br />classDefaultControllerextends Controller<br />{<br />/**<br /> * @Route("/hello/{name}")<br /> */<br />public functionindexAction($name)<br /> {<br />// ... do things<br />return $this->render(<br />'SensioHelloBundle:Default:index.html.twig',<br />array('name'=> $name)<br /> );<br /> }<br />}<br />
  21. 21. RequestHandling<br />classDefaultControllerextends Controller<br />{<br />/**<br /> * @Route("/schedule")<br /> *@Template()<br />*/<br />public functionindexAction()<br /> {<br /> $title='ConferencesSchedule';<br />returnarray('title'=> $title);<br /> }<br />}<br />Template vars<br />
  22. 22. ViewRendering<br />{%extends"SensioConferenceBundle::layout.html.twig"%}<br />{%blockcontent%}<br /> <h1> {{title}} </h1><br /> <ul><br /> <li>Caching on the Edge, by Fabien Potencier</li><br /> <li>HipHop for PHP, by Scott Mac Vicar</li><br /> <li>XDebug, by Derick Rethans</li><br /> <li>...</li><br /> </ul><br />{%endblock%}<br />
  23. 23. Twig Template Engine<br />Twigis a modern templateengine for PHP<br /><ul><li>Fast
  24. 24. Concise and richsyntax
  25. 25. Automatic output escaping
  26. 26. Modern features
  27. 27. Extensible
  28. 28. Flexible</li></li></ul><li>Template inheritance<br />{%extends"SensioConferenceBundle::layout.html.twig"%}<br />{%block content %}<br /> <h1> {{title}} </h1><br /> <ul><br /> <li>Caching on the Edge, by Fabien Potencier</li><br /> <li>HipHop for PHP, by Scott Mac Vicar</li><br /> <li>XDebug, by Derick Rethans</li><br /> <li>...</li><br /> </ul><br />{%endblock%}<br />index.html.twig<br />
  29. 29. Template inheritance<br />{%extends"::base.html.twig"%}<br />{%blockbody%}<br /> <imgsrc="/images/logo.gif" alt="Confoo 2011"/><br />{%blockcontent%}{%endblock%}<br />{%endblock%}<br />layout.html.twig<br />
  30. 30. <!DOCTYPE html><br /><html><br /> <head><br /> <meta http-equiv="Content-Type" <br /> content="text/html; charset=utf-8" /><br /> <title><br />{%blocktitle%}Welcome!{%endblock%}<br /></title><br /> <link rel="shortcut icon" <br />href="{{asset('favicon.ico') }}" /><br /> </head><br /> <body><br />{%blockbody%}{%endblock%}<br /> </body><br /></html><br />base.html.twig<br />
  31. 31. Template inheritance<br />base.html.twig<br />layout.html.twig<br />index.html.twig<br />
  32. 32. Smart URIs<br />
  33. 33. Smart URIs<br />Native routingmechanism<br />Bidirectional<br />Parametersconstraints support<br />
  34. 34. classDefaultControllerextends Controller<br />{<br />/**<br />* @Route(<br /> * "/{year}/talk/{month}/{day}/{slug}", <br /> * requirements={<br /> * "year"="d{4}",<br /> * "month"="d{2}",<br /> * "day"="d{2}"<br /> * }<br /> * )<br /> * @Template()<br /> */<br />public functionshowAction($slug, $day, $month, $year)<br />{<br />// ...<br /> }<br />}<br />
  35. 35. Doctrine ParameterConverter<br />Convertsrequestsparameters to a Doctrine entity.<br />classDefaultControllerextends Controller<br />{<br />/**<br />* @Route("/talk/{id}")<br /> * @ParamConverter("talk", class="SensioConferenceBundle:Talk")<br /> * @Template()<br /> */<br />public functionshowAction(Talk $talk)<br />{<br />returnarray('talk'=> $talk);<br /> }<br />}<br />
  36. 36. Easy<br />Debugging<br />http://www.flickr.com/photos/artelaphe/<br />
  37. 37. The Web DebugToolbar<br />Memory<br />Queries<br />Recorded logs<br />Timers<br />Currentenvironment<br />Currentresponse<br />Symfony2 version<br />PHP environment<br />
  38. 38. The Profiler Application<br />
  39. 39. The Profiler Application<br />
  40. 40. Exception Stack Trace<br />
  41. 41. Exception Stack Trace<br />
  42. 42. Recorded Logs<br />
  43. 43. http://www.flickr.com/photos/chanceprojects/<br />
  44. 44. Doctrine2 Support<br /><ul><li>Database Abstraction Layer on top of PDO
  45. 45. Object Relational Mapper
  46. 46. Migrations support
  47. 47. Object Document Mapper (MongoDB)
  48. 48. Object XML Mapper (XML databases)</li></li></ul><li>Data Mapper Implementation<br />/**<br /> * @ORMEntity()<br />*/<br />class Talk<br />{<br />/**<br /> * @ORMId()<br /> * @ORMGeneratedValue()<br /> * @ORMColumn(type="integer")<br /> */<br />private$id;<br />/** @ORMColumn(length=80) */<br />private $title;<br />/** @ORMColumn(type="text") */<br />private $synopsis;<br />/** @ORMColumn(type="datetime") */<br />private $schedule;<br />/** @ORMManyToMany(targetEntity="Speaker", mappedBy="talks") */<br />private $speakers;<br />}<br />
  49. 49. Validation<br />
  50. 50. Validation Framework<br /><ul><li>ValidatePOPOs (properties & methods)
  51. 51. Easy configuration with annotations
  52. 52. Easy to customize and extend</li></li></ul><li>namespaceSensioBundleTodoBundleEntity;<br />classTask<br />{<br />private$name;<br />private $dueDate;<br />public functiongetName() {<br />return $this->name;<br /> }<br />public functionsetName($name) {<br /> $this->name = $name;<br /> }<br />public functiongetDueDate() {<br />return $this->dueDate;<br /> }<br />public functionsetDueDate(DateTime $dueDate=null) {<br /> $this->dueDate= $dueDate;<br /> }<br />}<br />
  53. 53. namespaceSensioBundleTodoBundleEntity;<br />useSymfonyComponentValidatorConstraintsasAssert;<br />classTask<br />{<br />/**<br /> * @AssertNotBlank()<br /> * @AssertMinLength(5)<br /> * @AssertMaxLength(30)<br /> */<br />private $name;<br />/**<br /> * @AssertNotBlank()<br /> * @AssertType()<br /> * @AssertMaxLength(30)<br /> */<br />private $dueDate;<br />// ...<br />}<br />
  54. 54. Forms Management<br />http://www.flickr.com/photos/miahz/<br />
  55. 55. Forms Management<br /><ul><li>Transparent layer on top of yourdomainobject
  56. 56. Native CSRF protection
  57. 57. Coupled to the Validation framework
  58. 58. Twigintegration</li></li></ul><li>namespaceSensioBundleTodoBundleForm;<br />useSymfonyComponentFormAbstractType;<br />useSymfonyComponentFormFormBuilder;<br />classTaskTypeextendsAbstractType<br />{<br />public functionbuildForm(FormBuilder $builder, array $options)<br /> {<br /> $builder->add('name');<br /> $builder->add('dueDate', 'date');<br /> }<br />public functiongetName()<br /> {<br />return'task';<br /> }<br />}<br />
  59. 59. useSensioBundleTodoBundleEntityTask;<br />useSensioBundleTodoBundleFormTaskType;<br />public functionnewAction()<br />{<br /> $task =newTask();<br /> $task->setName('Write a blog post');<br /> $task->setDueDate(new DateTime('tomorrow'));<br /> $request = $this->getRequest(); <br /> $form = $this->createForm(newTaskType(), $task);<br />if ($request->getMethod() =='POST') {<br /> $form->bindRequest($request);<br />if ($form->isValid()) {<br />// save the task to the database...<br />return $this->redirect($this->generateUrl('success'));<br /> }<br /> }<br />}<br />
  60. 60. Prototyping<br />{%extends'SensioTodoBundle::layout.html.twig'%}<br />{%blockcontent%}<br /><form action="#" method="post"><br />{{form_widget(form) }}<br /> <input type="submit" value="Send!" /><br /></form><br />{%endblock%}<br />
  61. 61. FunctionalTesting<br />http://www.flickr.com/photos/kenstein/<br />
  62. 62. FunctionalTesting<br />Simulating an end-user browsing<br />Crawling API for links & forms<br />Testinginternalobjects<br />Testing the response<br />
  63. 63. FunctionalTesting<br />classDefaultControllerTestextendsWebTestCase<br />{<br />public functiontestIndex()<br /> {<br /> $client =static::createClient();<br /> $crawler = $client->request('GET', '/schedule');<br /> $this->assertTrue(<br /> $crawler->filter('html:contains("Fabien")')->count() >0<br /> );<br /> $response = $client->getResponse();<br /> $this->assertTrue($response->headers->has('expires'));<br /> }<br />}<br />
  64. 64. HTTP Compliance (RFC2616)<br />
  65. 65. Expiration / Validation<br />
  66. 66. Expiration – Expires Header Field<br />classDefaultControllerextends Controller<br />{<br />/**<br /> * @Route("/schedule")<br /> * @Template<br />* @Cache(expires="tomorrow")<br />*/<br />public functionindexAction()<br /> {<br /> $title='ConferencesSchedule';<br />returnarray('title'=> $title);<br /> }<br />}<br />
  67. 67. Expiration – Cache-Control Header Field<br />classDefaultControllerextends Controller<br />{<br />/**<br /> * @Route("/schedule")<br /> * @Template<br />* @Cache(maxage="20")<br />*/<br />public functionindexAction()<br /> {<br /> $title='ConferencesSchedule';<br />returnarray('title'=> $title);<br /> }<br />}<br />
  68. 68. Native PHP Reverse Proxy Cache<br />
  69. 69. Varnish / Squid<br />
  70. 70. http://varnish-cache.org<br />
  71. 71. EdgeSideIncludes<br /><esi:includesrc="http://..." /><br />
  72. 72. EdgeSideIncludes Support<br />No ESI<br />
  73. 73. EdgeSideIncludes Support<br />With ESI<br /><esi:include … /><br />
  74. 74. Interactive<br />Code Generators<br />
  75. 75. $ phpapp/console generate:bundle<br />
  76. 76.
  77. 77. $ phpapp/console generate:doctrine:crud<br />
  78. 78. http://www.flickr.com/photos/bwop/<br />
  79. 79. <?xml version="1.0"?><br /><xliff version="1.2"<br />xmlns="urn:oasis:names:tc:xliff:document:1.2"><br /> <file source-language="en"<br />datatype="plaintext"<br /> original="file.ext"><br /> <body><br /> <trans-unit id="1"><br /> <source>Symfony2 isgreat</source><br /> <target>J'aime Symfony2</target><br /> </trans-unit><br /> <trans-unit id="2"><br /> <source>My name is %name%!</source><br /> <target>Je m'appelle %name% !</target><br /> </trans-unit><br /> </body><br /> </file><br /></xliff><br />
  80. 80. Translating Messages FromTwig<br />{%setmessage = 'Symfony2 isgreat'%}<br />{{message|trans}}<br />{%setmessage = 'Mynameis %name%!'%}<br />{{message|trans({'%name%': 'Hugo'}, "hello") }}<br />
  81. 81. http://www.flickr.com/photos/cstein96/<br />
  82. 82. Roadmap for 2.1?<br />http://www.flickr.com/photos/mkrigsman/<br />
  83. 83. Thank You!<br />

×