A Practical Introduction to Symfony2

11,856 views
11,718 views

Published on

An introductory Symfony2 talk given at PHP Matsuri in Tokyo, Japan.

Published in: Technology

A Practical Introduction to Symfony2

  1. 1. A Practical Introduction to Symfony2 Kris Wallsmith PHP Matsuri • October 2, 2010 Saturday, October 2, 2010
  2. 2. @kriswallsmith • Release Manager for symfony 1.3 & 1.4 • Doctrine contributor • Senior Software Engineer at • 10 years experience in web development • Open source evangelist and international speaker Saturday, October 2, 2010
  3. 3. the evolution of symfony • Mojavi 3 • symfony (2007) • Symfony2 (2011) Saturday, October 2, 2010
  4. 4. a quick note for the case-sensitive among us Saturday, October 2, 2010
  5. 5. talk about “symfony” Saturday, October 2, 2010
  6. 6. talk about “symfony 1” Saturday, October 2, 2010
  7. 7. talk about “Symfony2” Saturday, October 2, 2010
  8. 8. there is no “Symfony 1” Saturday, October 2, 2010
  9. 9. there is no “symfony 2” Saturday, October 2, 2010
  10. 10. there is no “Symfony 2” Saturday, October 2, 2010
  11. 11. there is no “Symfony 2” { less search-friendly Saturday, October 2, 2010
  12. 12. Symfony2 Saturday, October 2, 2010
  13. 13. # Symfony2 Saturday, October 2, 2010
  14. 14. the evolution of symfony • Mojavi 3 • symfony (2007) • Symfony2 (2011) Saturday, October 2, 2010
  15. 15. what’s old? Saturday, October 2, 2010
  16. 16. what’s old? • same philosophy as symfony 1 Saturday, October 2, 2010
  17. 17. what’s old? • same philosophy as symfony 1 • don’t reinvent the wheel Saturday, October 2, 2010
  18. 18. what’s old? • same philosophy as symfony 1 • don’t reinvent the wheel • loosely-coupled components Saturday, October 2, 2010
  19. 19. what’s old? • same philosophy as symfony 1 • don’t reinvent the wheel • loosely-coupled components • predictable conventions Saturday, October 2, 2010
  20. 20. what’s old? • same philosophy as symfony 1 • don’t reinvent the wheel • loosely-coupled components • predictable conventions • highly configurable Saturday, October 2, 2010
  21. 21. what’s old? • same philosophy as symfony 1 • don’t reinvent the wheel • loosely-coupled components • predictable conventions • highly configurable • testable Saturday, October 2, 2010
  22. 22. what’s old? • same philosophy as symfony 1 • don’t reinvent the wheel • loosely-coupled components • predictable conventions • highly configurable • testable • awesome developer tools Saturday, October 2, 2010
  23. 23. what’s new? Saturday, October 2, 2010
  24. 24. what’s new? • PHP 5.3 • a brand new foundation Saturday, October 2, 2010
  25. 25. what’s new? • PHP 5.3 • a brand new foundation • more smart, more lazy Saturday, October 2, 2010
  26. 26. what’s new? • PHP 5.3 • a brand new foundation • more smart, more lazy • REALLY REALLY FAST Saturday, October 2, 2010
  27. 27. what’s new? • PHP 5.3 • a brand new foundation • more smart, more lazy • REALLY REALLY FAST Saturday, October 2, 2010
  28. 28. PHP 5.3 Saturday, October 2, 2010
  29. 29. PHP 5.3 • namespaces • closures Saturday, October 2, 2010
  30. 30. Saturday, October 2, 2010
  31. 31. HTTPMessageRequest Saturday, October 2, 2010
  32. 32. HTTPMessageRequest Saturday, October 2, 2010
  33. 33. Saturday, October 2, 2010
  34. 34. Saturday, October 2, 2010
  35. 35. Saturday, October 2, 2010
  36. 36. HTTPClientRequest Saturday, October 2, 2010
  37. 37. HTTPClientRequest Saturday, October 2, 2010
  38. 38. Saturday, October 2, 2010
  39. 39. Saturday, October 2, 2010
  40. 40. Saturday, October 2, 2010
  41. 41. Saturday, October 2, 2010
  42. 42. Saturday, October 2, 2010
  43. 43. Saturday, October 2, 2010
  44. 44. Saturday, October 2, 2010
  45. 45. closures • anonymous functions • lambda functions Saturday, October 2, 2010
  46. 46. Saturday, October 2, 2010
  47. 47. Saturday, October 2, 2010
  48. 48. Saturday, October 2, 2010
  49. 49. Saturday, October 2, 2010
  50. 50. Saturday, October 2, 2010
  51. 51. a new foundation Saturday, October 2, 2010
  52. 52. anatomy of a Symfony2 request Saturday, October 2, 2010
  53. 53. anatomy of a Symfony2 request • Kernel Saturday, October 2, 2010
  54. 54. anatomy of a Symfony2 request • Kernel • Request Saturday, October 2, 2010
  55. 55. anatomy of a Symfony2 request • Kernel • Request • Controller Saturday, October 2, 2010
  56. 56. anatomy of a Symfony2 request • Kernel • Request • Controller • Response Saturday, October 2, 2010
  57. 57. anatomy of a Symfony2 request Saturday, October 2, 2010
  58. 58. anatomy of a Symfony2 request • index.php creates a Kernel Saturday, October 2, 2010
  59. 59. anatomy of a Symfony2 request • index.php creates a Kernel • the kernel creates a Request Saturday, October 2, 2010
  60. 60. anatomy of a Symfony2 request • index.php creates a Kernel • the kernel creates a Request • the kernel passes the Request to the ControllerResolver Saturday, October 2, 2010
  61. 61. anatomy of a Symfony2 request • index.php creates a Kernel • the kernel creates a Request • the kernel passes the Request to the ControllerResolver • the ControllerResolver returns a callable Saturday, October 2, 2010
  62. 62. anatomy of a Symfony2 request • index.php creates a Kernel • the kernel creates a Request • the kernel passes the Request to the ControllerResolver • the ControllerResolver returns a callable • the kernel calls the callable Saturday, October 2, 2010
  63. 63. anatomy of a Symfony2 request • index.php creates a Kernel • the kernel creates a Request • the kernel passes the Request to the ControllerResolver • the ControllerResolver returns a callable • the kernel calls the callable • the callable returns a Response Saturday, October 2, 2010
  64. 64. Silex http://github.com/fabpot/Silex Saturday, October 2, 2010
  65. 65. just enough, nothing more Saturday, October 2, 2010
  66. 66. Saturday, October 2, 2010
  67. 67. switch ($_GET['pg']) case 'edit': // ... Saturday, October 2, 2010
  68. 68. switch ($_GET['pg']) case 'edit': // ... Saturday, October 2, 2010
  69. 69. Any volunteers to rewrite WordPress in Silex? Saturday, October 2, 2010
  70. 70. quick tour Saturday, October 2, 2010
  71. 71. frontend/ src/ web/ Saturday, October 2, 2010
  72. 72. frontend/ FrontendKernel.php cache/ config/ console logs/ phpunit.xml Saturday, October 2, 2010
  73. 73. src/ autoload.php Application/ Bundle/ vendor/ symfony/ doctrine/ Saturday, October 2, 2010
  74. 74. web/ css/ images/ index.php index_dev.php js/ Saturday, October 2, 2010
  75. 75. ../ MainBundle/ Controller/ MainBundle.php Resources/ config/ views/ Tests/ Saturday, October 2, 2010
  76. 76. How do I use it? Saturday, October 2, 2010
  77. 77. # frontend/config/routing.yml homepage: pattern: / defaults: _controller: MainBundle:Main:index requirements: _method: get Saturday, October 2, 2010
  78. 78. // src/Application/MainBundle/Controller/MainController.php namespace ApplicationMainBundleController; class MainController extends Controller { public function indexAction() { return $this->render('MainBundle:Main:index.php'); } } Saturday, October 2, 2010
  79. 79. homepage: pattern: / defaults: _controller: MainBundle:Main:index requirements: _method: get namespace ApplicationMainBundleController; class MainController extends Controller { public function indexAction() { return $this->render('MainBundle:Main:index.php'); } } Saturday, October 2, 2010
  80. 80. homepage: pattern: / defaults: _controller: MainBundle:Main:index requirements: _method: get namespace ApplicationMainBundleController; class MainController extends Controller { public function indexAction() { return $this->render('MainBundle:Main:index.php'); } } Saturday, October 2, 2010
  81. 81. homepage: pattern: / defaults: _controller: MainBundle:Main:index requirements: _method: get namespace ApplicationMainBundleController; class MainController extends Controller { public function indexAction() { return $this->render('MainBundle:Main:index.php'); } } Saturday, October 2, 2010
  82. 82. homepage: pattern: / defaults: _controller: MainBundle:Main:index requirements: _method: get namespace ApplicationMainBundleController; class MainController extends Controller { public function indexAction() { return $this->render('MainBundle:Main:index.php'); } } Saturday, October 2, 2010
  83. 83. homepage: pattern: / defaults: _controller: MainBundle:Main:index requirements: _method: get namespace ApplicationMainBundleController; class MainController extends Controller { public function indexAction() { return $this->render('MainBundle:Main:index.php'); } } Saturday, October 2, 2010
  84. 84. homepage: pattern: / defaults: _controller: MainBundle:Main:index requirements: _method: get namespace ApplicationMainBundleController; class MainController extends Controller { public function indexAction() { return $this->render('MainBundle:Main:index.php'); } } Saturday, October 2, 2010
  85. 85. homepage: pattern: /:year/:slug defaults: _controller: MainBundle:Blog:showArticle requirements: year: d{4} namespace ApplicationMainBundleController; class BlogController extends Controller { public function showArticleAction($slug, $year) { // ... return $this->render('MainBundle:Blog:showArticle.php', array('article' => $article)); } } Saturday, October 2, 2010
  86. 86. homepage: pattern: /:year/:slug defaults: _controller: MainBundle:Blog:showArticle requirements: year: d{4} namespace ApplicationMainBundleController; class BlogController extends Controller { public function showArticleAction($slug, $year) { // ... return $this->render('MainBundle:Blog:showArticle.php', array('article' => $article)); } } Saturday, October 2, 2010
  87. 87. homepage: pattern: /:year/:slug defaults: _controller: MainBundle:Blog:showArticle requirements: year: d{4} namespace ApplicationMainBundleController; class BlogController extends Controller { public function showArticleAction($slug, $year) { // ... return $this->render('MainBundle:Blog:showArticle.php', array('article' => $article)); } } Saturday, October 2, 2010
  88. 88. homepage: pattern: /:year/:slug defaults: _controller: MainBundle:Blog:showArticle requirements: year: d{4} namespace ApplicationMainBundleController; class BlogController extends Controller { public function showArticleAction($slug, $year) { // ... return $this->render('MainBundle:Blog:showArticle.php', array('article' => $article)); } } Saturday, October 2, 2010
  89. 89. homepage: pattern: /:year/:slug defaults: _controller: MainBundle:Blog:showArticle requirements: year: d{4} namespace ApplicationMainBundleController; class BlogController extends Controller { public function showArticleAction($slug, $year) { // ... return $this->render('MainBundle:Blog:showArticle.php', array('article' => $article)); } } Saturday, October 2, 2010
  90. 90. MainBundle/Resources/ config/ views/ Blog/ showArticle.php Main/ error404.php index.php layout.php Saturday, October 2, 2010
  91. 91. return $this->render('MainBundle:Blog:showArticle.php', array('article' => $article)); MainBundle/Resources/ config/ views/ Blog/ showArticle.php Main/ error404.php index.php layout.php Saturday, October 2, 2010
  92. 92. return $this->render('MainBundle:Blog:showArticle.php', array('article' => $article)); MainBundle/Resources/ config/ views/ Blog/ showArticle.php Main/ error404.php index.php layout.php Saturday, October 2, 2010
  93. 93. return $this->render('MainBundle:Blog:showArticle.php', array('article' => $article)); MainBundle/Resources/ config/ views/ Blog/ showArticle.php Main/ error404.php index.php layout.php Saturday, October 2, 2010
  94. 94. return $this->render('MainBundle:Blog:showArticle.php', array('article' => $article)); MainBundle/Resources/ config/ views/ Blog/ showArticle.php Main/ error404.php index.php layout.php Saturday, October 2, 2010
  95. 95. return $this->render('MainBundle:Blog:showArticle.php', array('article' => $article)); MainBundle/Resources/ config/ views/ Blog/ showArticle.php Main/ error404.php index.php layout.php Saturday, October 2, 2010
  96. 96. return $this->render('MainBundle:Blog:showArticle.php', array('article' => $article)); MainBundle/Resources/ config/ views/ Blog/ showArticle.php Main/ error404.php index.php layout.php Saturday, October 2, 2010
  97. 97. return $this->render('MainBundle:Blog:showArticle.twig', array('article' => $article)); MainBundle/Resources/ config/ views/ Blog/ showArticle.twig Main/ error404.php index.php layout.php Saturday, October 2, 2010
  98. 98. return $this->render('MainBundle:Blog:showArticle.twig', array('article' => $article)); MainBundle/Resources/ config/ views/ Blog/ showArticle.twig Main/ error404.php index.php layout.php Saturday, October 2, 2010
  99. 99. Twig The flexible, fast, and secure template language for PHP http://twig-project.org Saturday, October 2, 2010
  100. 100. symfony 1 Saturday, October 2, 2010
  101. 101. symfony 1 • templates Saturday, October 2, 2010
  102. 102. symfony 1 • templates • layouts Saturday, October 2, 2010
  103. 103. symfony 1 • templates • layouts • slots Saturday, October 2, 2010
  104. 104. symfony 1 • templates • layouts • slots • components Saturday, October 2, 2010
  105. 105. symfony 1 • templates • layouts • slots • components • partials Saturday, October 2, 2010
  106. 106. symfony 1 • templates • layouts • slots • components • partials • component slots Saturday, October 2, 2010
  107. 107. fewer concepts, more power Saturday, October 2, 2010
  108. 108. Symfony2 Saturday, October 2, 2010
  109. 109. Symfony2 • templates Saturday, October 2, 2010
  110. 110. Symfony2 • templates • slots Saturday, October 2, 2010
  111. 111. Symfony2 • • templates slots } fewer concepts, more power Saturday, October 2, 2010
  112. 112. <?php $view->extend('MainBundle::layout.php') ?> <?php foreach ($people as $person): ?> <?php $view->render( 'MainBundle:Person:thumbnail', array('person' => $person) ) ?> <?php endforeach; ?> Saturday, October 2, 2010
  113. 113. <?php $view->extend('MainBundle::layout.php') ?> <?php foreach ($people as $person): ?> decorate_with() <?php $view->render( 'MainBundle:Person:thumbnail', array('person' => $person) ) ?> <?php endforeach; ?> Saturday, October 2, 2010
  114. 114. <?php $view->extend('MainBundle::layout.php') ?> <?php foreach ($people as $person): ?> <?php $view->render( 'MainBundle:Person:thumbnail', array('person' => $person) ) ?> <?php endforeach; ?> Saturday, October 2, 2010
  115. 115. <?php $view->extend('MainBundle::layout.php') ?> <?php foreach ($people as $person): ?> <?php $view->render( 'MainBundle:Person:thumbnail', array('person' => $person) ) ?> <?php endforeach; ?> Saturday, October 2, 2010
  116. 116. <?php $view->extend('MainBundle::layout.php') ?> <?php foreach ($people as $person): ?> <?php $view->render( 'MainBundle:Person:thumbnail', array('person' => $person) ) ?> include_partial() <?php endforeach; ?> Saturday, October 2, 2010
  117. 117. <?php $view->extend('MainBundle::layout.php') ?> <?php foreach ($people as $person): ?> <?php $view->render( 'MainBundle:Person:thumbnail', array('person' => $person) ) ?> <?php endforeach; ?> Saturday, October 2, 2010
  118. 118. helpers Saturday, October 2, 2010
  119. 119. <?php $view['slots']->set('title', 'Hi!') ?> <?php $view['slots']->start('sidebar') ?> My awesome sidebar! <?php $view['slots']->stop() ?> Saturday, October 2, 2010
  120. 120. <?php $view['slots']->set('title', 'Hi!') ?> <?php $view['slots']->start('sidebar') ?> My awesome sidebar! <?php $view['slots']->stop() ?> Saturday, October 2, 2010
  121. 121. helpers are objects Saturday, October 2, 2010
  122. 122. $view['javascripts']->add('script.js'); echo $view['javascripts']; echo $view['assets']->getUrl('logo.gif'); use_javascript() echo $view['router']->generate( 'person_show', array('username' => $username) ); $view['actions']->output('MainBundle:Search:form'); Saturday, October 2, 2010
  123. 123. $view['javascripts']->add('script.js'); echo $view['javascripts']; echo $view['assets']->getUrl('logo.gif'); include_javascripts() echo $view['router']->generate( 'person_show', array('username' => $username) ); $view['actions']->output('MainBundle:Search:form'); Saturday, October 2, 2010
  124. 124. $view['javascripts']->add('script.js'); echo $view['javascripts']; echo $view['assets']->getUrl('logo.gif'); echo $view['router']->generate( 'person_show', public_path() array('username' => $username) ); $view['actions']->output('MainBundle:Search:form'); Saturday, October 2, 2010
  125. 125. $view['javascripts']->add('script.js'); echo $view['javascripts']; echo $view['assets']->getUrl('logo.gif'); echo $view['router']->generate( 'person_show', array('username' => $username) ); url_for() $view['actions']->output('MainBundle:Search:form'); Saturday, October 2, 2010
  126. 126. $view['javascripts']->add('script.js'); echo $view['javascripts']; echo $view['assets']->getUrl('logo.gif'); echo $view['router']->generate( include_component() 'person_show', array('username' => $username) ); $view['actions']->output('MainBundle:Search:form'); Saturday, October 2, 2010
  127. 127. dependency injection Saturday, October 2, 2010
  128. 128. lazy objects Saturday, October 2, 2010
  129. 129. “ if you want me to foo you better give me the foo-er Saturday, October 2, 2010 ”
  130. 130. class User { protected $session; public function __construct(Session $session) { $this->session = $session; } } Saturday, October 2, 2010
  131. 131. class User { protected $session; public function __construct() { $this->session = Session::factory(); } } Saturday, October 2, 2010
  132. 132. class User { protected $session; public function __construct() { $this->session = Session::factory(); } } Saturday, October 2, 2010
  133. 133. $session = $this->getMock('Session') ->expects($this->any()) ->method('get') ->with('foo') ->will($this->returnValue('bar')) ; // inject the mock object! $user = new User($session); $this->assertEquals('bar', $user->getSessionVar('foo')); Saturday, October 2, 2010
  134. 134. dependency injection container • a configuration layer • creates a "container" that manages the creation of objects • “teach” the container • using xml, yaml, php, ini (or some combination) Saturday, October 2, 2010
  135. 135. services: session: class: Session user: class: User arguments: - @session Saturday, October 2, 2010
  136. 136. public function getUserService() { if (isset($this->shared['user'])) return $this->shared['user']; $user = new User( $this->getSessionService() ); $this->shared['user'] = $user; return $user; } Saturday, October 2, 2010
  137. 137. // get one service by name $container->get('user'); Saturday, October 2, 2010
  138. 138. // find many services by "tag" $c->findTaggedServiceIds('my_tag'); Saturday, October 2, 2010
  139. 139. services: foo_helper: class: Foo tags: - name: my_tag Saturday, October 2, 2010
  140. 140. container parameters Saturday, October 2, 2010
  141. 141. parameters: foo.class: Foo services: foo: class: %foo.class% Saturday, October 2, 2010
  142. 142. parameters: foo.class: Foo services: foo: class: %foo.class% Saturday, October 2, 2010
  143. 143. parameters: foo.class: Foo services: foo: class: %foo.class% Saturday, October 2, 2010
  144. 144. dependency injection extensions semantic configuration Saturday, October 2, 2010
  145. 145. doctrine.dbal: dbname: xxx user: xxx password: xxx doctrine.orm: ~ Saturday, October 2, 2010
  146. 146. awesome developer tools Saturday, October 2, 2010
  147. 147. Web Debug Toolbar Saturday, October 2, 2010
  148. 148. Web Debug Toolbar Saturday, October 2, 2010
  149. 149. Web Debug Toolbar Saturday, October 2, 2010
  150. 150. Web Profiler Saturday, October 2, 2010
  151. 151. Web Profiler Saturday, October 2, 2010
  152. 152. Web Profiler Saturday, October 2, 2010
  153. 153. Web Profiler Saturday, October 2, 2010
  154. 154. Web Profiler Saturday, October 2, 2010
  155. 155. Questions? Saturday, October 2, 2010
  156. 156. OpenSky is Hiring! http://engineering.shopopensky.com Please contact me if you're interested. Saturday, October 2, 2010
  157. 157. OpenSky is Hiring! http://engineering.shopopensky.com Please contact me if you're interested. Saturday, October 2, 2010
  158. 158. symfony-reloaded.org Saturday, October 2, 2010

×