Symfony 2.0 on PHP 5.3
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Symfony 2.0 on PHP 5.3

on

  • 14,080 views

 

Statistics

Views

Total Views
14,080
Views on SlideShare
12,141
Embed Views
1,939

Actions

Likes
21
Downloads
394
Comments
1

19 Embeds 1,939

http://www.symfony.es 1374
http://asiermarques.com 283
http://www.symfolive.com 175
http://www.slideshare.net 24
http://www.php.rk.edu.pl 23
http://symfony.es 22
http://raulbarraltamayo.wordpress.com 13
http://www.iweb34.com 5
http://translate.googleusercontent.com 4
http://dev.symfony2developer.com 3
http://webcache.googleusercontent.com 2
http://paper.li 2
http://www.mefeedia.com 2
http://dev.synchvideos.com 2
http://209.85.229.132 1
http://www.asiermarques.com 1
http://www.mybyte.co.za 1
http://www.linkedin.com 1
http://static.slidesharecdn.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

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

Symfony 2.0 on PHP 5.3 Presentation Transcript

  • 1. Symfony 2.0 on PHP 5.3! Fabien Potencier
  • 2. Fabien Potencier •  Serial entrepreneur and developer by passion •  Founder of Sensio (in 1998) –  A services and consulting company specialized in Web technologies and Internet marketing (France and USA) –  70 people –  Open-Source specialists –  Big corporate customers –  Consulting, training, development, web design, … and more –  Sponsor of a lot of Open-Source projects like symfony and Doctrine
  • 3. Fabien Potencier •  Creator and lead developer of symfony… •  and creator and lead developer of some more: –  symfony components –  Swift Mailer : Powerful component based mailing library for PHP –  Twig : Fexible, fast, and secure template language for PHP –  Pirum : Simple PEAR Channel Server Manager –  Sismo : PHP continuous integration server –  Lime : Easy to use unit testing library for PHP –  Twitto : A web framework in a tweet –  Twittee : A Dependency Injection Container in a tweet –  Pimple : A small PHP 5.3 dependency injection container
  • 4. Fabien Potencier •  Read my technical blog: http://fabien.potencier.org/ •  Follow me on Twitter: @fabpot •  Fork my code on Github: http://github.com/fabpot/
  • 5. How many of you have used symfony? 1.0? 1.1? 1.2? 1.3?
  • 6. symfony 1.0 – January 2007 •  Started as a glue between existing Open-Source libraries: – Mojavi (heavily modified), Propel, Prado i18n, … •  Borrowed concepts from other languages and frameworks: – Routing, CLI, functional tests, YAML, Rails helpers… •  Added new concepts to the mix – Web Debug Toolbar, admin generator, configuration cascade, …
  • 7. symfony 1.2 – November 2008 •  Decoupled but cohesive components: the symfony platform –  Forms, Routing, Cache, YAML, ORMs, … •  Controller still based on Mojavi –  View, Filter Chain, …
  • 8. Roadmap •  1.0 – January 2007 •  1.1 – June 2008 •  1.2 – November 2008 •  1.3 – November 2009 •  1.4 – Last 1.X version (LTS release : 3 years of support) – same as 1.3 but without deprecated features •  Version 2.0 – Hopefully at the end of 2010
  • 9. Symfony 2.0 •  PHP 5.3 only - http://sf-to.org/sf20onPHP53 •  Same Symfony core components (updated for PHP 5.3) •  Different controller implementation •  Oh! Symfony now takes a capital S!!!
  • 10. Symfony Components •  Standalone components •  Packaged individually •  Upcoming dedicated website –  http://components.symfony-project.org/ •  Dedicated section for each component •  Dedicated documentation •  Dedicated Subversion repository –  http://svn.symfony-project.com/components/ •  Git mirror –  http://github.com/fabpot •  Already published components: –  YAML, Dependency Injection, Event Dispatcher, Templating
  • 11. Symfony Components •  Existing components –  will soon be released as 1.0 (for PHP 5.2) –  will then be migrated to PHP 5.3 (mainly introducing namespaces) •  New components: –  will work with PHP 5.3 only right from the start
  • 12. Symfony 2 main goals Flexibility Fast Smart
  • 13. Symfony 2 core Event Dispatcher Dependency Injection Container Controller Handling
  • 14. Symfony 2 •  Obviously not yet available as a full-stack MVC framework •  Some components have already been merged into Symfony 1 –  Event Dispatcher –  Form Framework •  Other new components will be released as standalone components: –  Controller Handling –  Output Escaping will be migrated to –  Forms PHP 5.3 soon –  Routing –  Templating Framework (done) –  Dependency Injection Container (done)
  • 15. symfony 1.X Not fast enough?
  • 16. symfony 1 is one of the slowest framework when you test it against a simple Hello World application
  • 17. 1644& 1544& !"#$%&!'!& 1344& Hello World 1144& Benchmark 1444& ;44& x 19.5 :44& 944& 844& 744& 644& 544& 344& ()"#*& x 2.3 144& +,& -./0)%.&123& 4& based on numbers from http://paul-m-jones.com/?p=315
  • 18. Conclusion?
  • 19. Don’t use symfony for your next « Hello World » website Use PHP ;)
  • 20. By the way, the fastest implemention of a Hello World application with PHP: die('Hello World');
  • 21. But symfony 1 is probably fast enough for your next website
  • 22. … anyway, it is fast enough for Yahoo! Yahoo! Bookmarks sf-to.org/bookmarks Yahoo! Answers sf-to.org/answers delicious.com sf-to.org/delicious
  • 23. … and recently dailymotion.com announced its migration to Symfony sf-to.org/dailymotion
  • 24. Second most popular video sharing website One of the top 30 websites in the world 59 million unique users in July 2009
  • 25. …and of course many other smaller websites…
  • 26. Symfony 2 Faster?
  • 27. Symfony 2 core is so light and flexible that its raw performance is outstanding
  • 28. require_once dirname(__FILE__).'/sf20/autoload2/sfCore2Autoload.class.php'; sfCore2Autoload::register(); Hello World $app = new HelloApplication(); $app->run()->send(); 0 class HelloApplication wit h Symfony 2. { public function __construct() { $this->dispatcher = new sfEventDispatcher(); $this->dispatcher->connect('application.load_controller', array($this, 'loadController')); } public function run() OUTDATED { $request = new sfWebRequest($this->dispatcher); $handler = new sfRequestHandler($this->dispatcher); $response = $handler->handle($request); return $response; } public function loadController(sfEvent $event) { $event->setReturnValue(array(array($this, 'hello'), array($this->dispatcher, $event['request']))); return true; } public function hello($dispatcher, $request) { $response = new sfWebResponse($dispatcher); $response->setContent('Hello World'); return $response; }
  • 29. require __DIR__.'/lib/Symfony/Core/ClassLoader.php'; use SymfonyComponentsEventDispatcherEvent; Hello World use SymfonyComponentsEventDispatcherEventDispatcher; use SymfonyComponentsRequestHandlerRequestHandler; ymfony 2.0 use SymfonyComponentsRequestHandlerRequest; use SymfonyComponentsRequestHandlerResponse; with S $classLoader = new ClassLoader('Symfony', __DIR__.'/lib'); $classLoader->register(); on PHP 5.3 $dispatcher = new EventDispatcher(); $dispatcher->connect('core.load_controller', function (Event $event) { $event->setReturnValue(array( function (Request $request) { return new Response('Hello '.$request->getQueryParameter('name')); }, array($event['request']) )); return true; }); $request = new Request(); $request->setQueryParameters(array('name' => 'Fabien')); $handler = new RequestHandler($dispatcher); $response = $handler->handle($request); $response->send();
  • 30. 7922& 7822& !"#$%&!'!& Hello World Benchmark ()$*+& 7022& 7722& 7222& >22& =22& <22& Symfony 2.0 on PHP 5.3 ;22& :22& ,-./+%-&012& x 10 922& x 3 x 7 822& 022& 3+"#4& 722& 56& ,-./+%-&710& 2& based on numbers from http://paul-m-jones.com/?p=315
  • 31. 10 times faster?! You won’t have such a difference for real applications as most of the time, the limiting factor is not the framework itself
  • 32. … and PHP 5.3 helps •  The Hello World code on PHP 5.3 is 50% faster than the one on PHP 5.2 (for the same code!) •  All frameworks will benefit from some speed improvements •  Again, real applications won’t have such a speed difference just by upgrading to PHP 5.3 ! Upgrad e to PHP 5.3 e It mean s performanc improveme nts for FREE
  • 33. 10 times faster?! •  Raw speed matters because – It demonstrates that the core « kernel » is very light – It allows you to use several Symfony frameworks within a single application with the same behavior but different optimizations: •  One full-stack framework optimized for ease of use (think symfony 1) •  One light framework optimized for speed (think Rails Metal ;))
  • 34. How many of you have used PHP 5.3?
  • 35. This presentation is full of … the new PHP developer best friend
  • 36. Namespaces from sfRequest to SymfonyCoreRequest use SymfonyCoreRequest; $request = new Request();
  • 37. Anonymous Functions $a = function ($msg) { echo $msg; } $a('Hello World');
  • 38. Symfony 2 The Event Dispatcher
  • 39. EventDispatcher •  Observer Design Pattern •  Based on Cocoa Notification Center // sfI18N $callback = array($this, 'listenToChangeCultureEvent'); $dispatcher->connect('user.change_culture', $callback); // sfUser $event = new Event($this, 'user.change_culture', array('culture' => $culture)); $dispatcher->notify($event); •  I18N and User are decoupled •  An event is defined by a unique string •  « Anybody » can listen to any event •  You can notify existing events or create new ones easily
  • 40. require __DIR__.'/lib/Symfony/Core/ClassLoader.php'; use SymfonyComponentsEventDispatcherEvent; use SymfonyComponentsEventDispatcherEventDispatcher; $classLoader = new ClassLoader('Symfony', __DIR__.'/lib'); $classLoader->register(); $dispatcher = new EventDispatcher(); $listener = function ($event) { echo sprintf("Hello %s!n", $event['name']); }; $dispatcher->connect('foo', $listener); Can be any PHP callable $event = new Event(null, 'foo', array('name' => 'Fabien')); $dispatcher->notify($event);
  • 41. Symfony 2 The Request Handler
  • 42. The Request Handler •  The backbone of Symfony 2 controller implementation •  Class to build web frameworks, not only MVC ones •  Based on a simple assumption: –  The input is a Request object –  The output is a Response object •  The Request object can be anything you want •  The Response object must implement a send() method
  • 43. The Request Handler use SymfonyComponentsRequestHandlerRequestHandler; use SymfonyComponentsRequestHandlerRequest; $handler = new RequestHandler($dispatcher); $request = new Request(); $response = $handler->handle($request); $response->send();
  • 44. The Request Handler •  The RequestHandler does several things: –  Notifies events –  Executes a callable (the controller) –  Ensures that the Request is converted to a Response object •  The framework is responsible for choosing the controller •  The controller is responsible for the conversion of the Request to a Response
  • 45. namespace SymfonyComponentsRequestHandler; use SymfonyComponentsEventDispatcherEvent; use SymfonyComponentsEventDispatcherEventDispatcher; class RequestHandler { protected $dispatcher = null; public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function handle(RequestInterface $request) { try { return $this->handleRaw($request); } catch (Exception $e) { // exception RequestHandler is $event = $this->dispatcher->notifyUntil(new Event($this, 'core.exception', array('request' => $request, 'exception' => $e))); if ($event->isProcessed()) { return $this->filterResponse($event->getReturnValue(), 'An "core.exception" listener returned a non response object.'); } less than 100 lines throw $e; } } public function handleRaw(RequestInterface $request) { of PHP code! // request $event = $this->dispatcher->notifyUntil(new Event($this, 'core.request', array('request' => $request))); if ($event->isProcessed()) { return $this->filterResponse($event->getReturnValue(), 'An "core.request" listener returned a non response object.'); } // load controller $event = $this->dispatcher->notifyUntil(new Event($this, 'core.load_controller', array('request' => $request))); if (!$event->isProcessed()) { throw new LogicException('Unable to load the controller.'); } list($controller, $arguments) = $event->getReturnValue(); // controller must be a callable if (!is_callable($controller)) { throw new LogicException(sprintf('The controller must be a callable (%s).', var_export($controller, true))); } // controller $event = $this->dispatcher->notifyUntil(new Event($this, 'core.controller', array('request' => $request, 'controller' => &$controller, 'arguments' => &$arguments))); if ($event->isProcessed()) { try { return $this->filterResponse($event->getReturnValue(), 'An "core.controller" listener returned a non response object.'); } catch (Exception $e) { $retval = $event->getReturnValue(); } } else { // call controller $retval = call_user_func_array($controller, $arguments); } // view $event = $this->dispatcher->filter(new Event($this, 'core.view'), $retval); return $this->filterResponse($event->getReturnValue(), sprintf('The controller must return a response (instead of %s).', is_object($event->getReturnValue()) ? 'an object of class '.get_class($event->getReturnValue()) : (string) $event->getReturnValue())); } protected function filterResponse($response, $message) { if (!$response instanceof ResponseInterface) { throw new RuntimeException($message); } $event = $this->dispatcher->filter(new Event($this, 'core.response'), $response); $response = $event->getReturnValue(); if (!$response instanceof ResponseInterface) { throw new RuntimeException('An "core.response" listener returned a non response object.'); } return $response; } public function getEventDispatcher() { return $this->dispatcher; } }
  • 46. Request Handler Events core.request core.load_controller core.controller core.view core.response core.exception
  • 47. core.response As the very last event notified, a listener can modify the Response object just before it is returned to the user
  • 48. core.response $dispatcher->connect('core.response', function (Event $event, Response $response) { $response->setContent( $response->getContent(). 'The Web Debug Toolbar' ); Content of the response is changed return $response; } );
  • 49. core.request •  The very first event notified •  It can act as a short-circuit event •  If one listener returns a Response object, it stops the processing
  • 50. core.request $dispatcher->connect('core.request', function (Event $event) { $event->setReturnValue( new Response('Website unavailable...') ); Don’t go any further! return true; } );
  • 51. core.load_controller •  The only event for which at least one listener must be connected to •  A listener must return –  A PHP callable (the controller) –  The arguments to pass to the callable
  • 52. core.load_controller $dispatcher->connect('core.load_controller', function (Event $event) { $event->setReturnValue(array( function () { return new Response('Hello World'); }, array() Whatever the request, )); always return Hello World return true; } );
  • 53. core.view The controller must return a Response object except if a listener can convert the controller returned value to a Response
  • 54. core.view $dispatcher->connect('core.load_controller', function (Event $event) { $event->setReturnValue(array( function () { return 'Hello World'; }, array() )); The controller returns a string, not a Response return true; } );
  • 55. core.view The value returned $dispatcher->connect('core.view', by the controller function (Event $event, $value) { if (is_string($value)) { The view “convert” the return new Response($value); controller returned value to a } Response if it’s a string return $value; } If not, it just returns the ); original value and it lets another view handle it if needed
  • 56. core.exception The request handler catches all exceptions and give a chance to listeners to return a Response object
  • 57. core.exception $dispatcher->connect('core.exception', function (Event $event) { $event->setReturnValue( new Response( 'An error occurred: '.$event['exception']->getMessage() ) ); Mask the exception and return a return true; “nice” message to the user } );
  • 58. Request Handler •  Several listeners can be attached to a single event •  Listeners are called in turn
  • 59. require __DIR__.'/lib/Symfony/Core/ClassLoader.php'; Hello World use SymfonyComponentsEventDispatcherEvent; use SymfonyComponentsEventDispatcherEventDispatcher; use SymfonyComponentsRequestHandlerRequestHandler; with use SymfonyComponentsRequestHandlerRequest; ts use SymfonyComponentsRequestHandlerResponse; Symfony 2.0 Componen $classLoader = new ClassLoader('Symfony', __DIR__.'/lib'); $classLoader->register(); $dispatcher = new EventDispatcher(); $dispatcher->connect('core.load_controller', function (Event $event) { $event->setReturnValue(array( function (Request $request) { return new Response('Hello '.$request->getQueryParameter('name')); }, array($event['request']) )); return true; }); $request = new Request(); $request->setQueryParameters(array('name' => 'Fabien')); $handler = new RequestHandler($dispatcher); $response = $handler->handle($request); $response->send();
  • 60. require __DIR__.'/lib/Symfony/Core/ClassLoader.php'; use SymfonyComponentsEventDispatcherEvent; use SymfonyComponentsEventDispatcherEventDispatcher; use SymfonyComponentsRequestHandlerRequestHandler; use SymfonyComponentsRequestHandlerRequest; use SymfonyComponentsRequestHandlerResponse; $classLoader = new ClassLoader('Symfony', __DIR__.'/lib'); $classLoader->register();
  • 61. Autoloading in PHP 5.3 •  Will be hopefully standardized for major/all PHP 5.3 frameworks/libraries •  Main goal: –  provide a better interoperability between PHP frameworks/libraries •  A group of people is discussing this “standard” (nothing decided yet) http://groups.google.com/group/php-standards
  • 62. Autoloading in PHP 5.3 •  Current proposal http://groups.google.com/group/php-standards/web/php-coding- standard-version-2 •  Used for this presentation examples •  Tested by real-world projects: –  Doctrine 2 –  Lithium –  Symfony 2 Components
  • 63. $dispatcher = new EventDispatcher(); $dispatcher->connect( 'core.load_controller', $controllerLoader );
  • 64. $controllerLoader = function (Event $event) { $event->setReturnValue(array( $controller, Can be any PHP callable array($event['request']) ); } Arguments to pass to the controller
  • 65. Arguments passed to the controller $controller = function (Request $request) { $name = $request->getQueryParameter('name'); return new Response('Hello '.$name); }; A controller should return a Response
  • 66. $request = new Request(); $request->setQueryParameters(array('name' => 'Fabien')); $handler = new RequestHandler($dispatcher); $response = $handler->handle($request); $response->send(); Sends the response to the browser
  • 67. Symfony 2 The Templating Framework
  • 68. New Templating Framework •  4 components –  Template Engine –  Template Renderers –  Template Loaders –  Template Storages •  Independant library
  • 69. require __DIR__.'/lib/Symfony/Core/ClassLoader.php'; use SymfonyComponentsTemplatingEngine; use SymfonyComponentsTemplatingLoaderFilesystemLoader; $classLoader = new ClassLoader('Symfony', __DIR__.'/lib'); $classLoader->register(); $loader = new FilesystemLoader( '/path/to/templates/%name%.php' ); $t = new Engine($loader); echo $t->render('index', array('name' => 'Fabien'));
  • 70. Template Loaders •  No assumption about where and how templates are to be found –  Filesystem –  Database –  Memory, … •  Template names are « logical » names: $loader = new FilesystemLoader('/path/to/templates/%name%.php');
  • 71. Template Renderers •  No assumption about the format of the templates •  Template names are prefixed with the renderer name: –  index == php:index –  user:index $t = new Engine($loader, array( 'user' => new ProjectTemplateRenderer(), 'php' => new PhpRenderer(), ));
  • 72. Template Embedding Hello <?php echo $name ?> <?php $this->render('embedded', array('name' => $name)) ?> <?php $this->render('smarty:embedded') ?>
  • 73. Template Inheritance <?php $this->extend('layout') ?> Hello <?php echo $name ?> <html> <head> </head> <body> <?php $this->output('content') ?> </body> </html>
  • 74. Template Slots <html> <head> <title><?php $this->output('title') ?></title> </head> <body> <?php $this->output('content') ?> </body> </html> <?php $this->set('title', 'Hello World! ') ?> <?php $this->start('title') ?> Hello World! <?php $this->stop() ?>
  • 75. Template Multiple Inheritance A layout can be decorated by another layout Each layout can override slots
  • 76. Templating A CMS example
  • 77. CMS Templating •  Imagine a CMS with the following features: –  The CMS comes bundled with default templates –  The developer can override default templates for a specific project –  The webmaster can override some templates •  The CMS and developer templates are stored on the filesystem and are written with pure PHP code •  The webmaster templates are stored in a database and are written in a simple templating language: Hello {{ name }}
  • 78. CMS Templating •  The CMS has several built-in sections and pages –  Each page is decorated by a layout, depending on the section –  Each section layout is decorated by a base layout cms/templates/ project/templates/ base.php base.php articles/ articles/ layout.php layout.php article.php article.php content.php
  • 79. articles/content.php <h1>{{ title }}</h1> <p> {{ content }} </p>
  • 80. articles/article.php <?php $this->extend('articles/layout') ?> <?php $this->set('title', $title) ?> <?php echo $this->render( 'user:articles/content', array('title' => $title, 'content' => $content) ) ?>
  • 81. articles/layout.php <?php $this->extend ('base') ?> <?php $this->set('title', 'Articles | '.$this->get('title')) ?> <?php $this->start('head') ?> <?php $this->output('head') ?> <link rel="stylesheet" type="text/css" media="all" href="/css/ articles.css" /> <?php $this->stop() ?> <?php $this->output('content') ?>
  • 82. articles/layout.php <?php $this->extend('base') ?> <?php $this->set('title', 'Articles | '.$this->get('title')) ?> <?php $this->stylesheets->add('/css/articles.css') ?> <?php $this->output('content') ?>
  • 83. base.php <html> <head> <title> <?php $this->output('title') ?> </title> <?php $this->output('head') ?> </head> <body> <?php $this->output('content') ?> </body> </html>
  • 84. Template Renderer $t = new Engine($loader, array( 'user' => new ProjectTemplateRenderer(), 'php' => new PhpRenderer(), ));
  • 85. Template Renderer use SymfonyComponentsTemplatingRendererRenderer; class ProjectTemplateRenderer extends Renderer { public function evaluate(Storage $template, array $parameters = array()) { if ($template instanceof FileStorage) { $template = file_get_contents($template); } $this->parameters = $parameters; return preg_replace_callback('/{{s*(.+?)s*}}/', array($this, 'replaceParameters'), $template); } public function replaceParameters($matches) { return isset($this->parameters[$matches[1]]) ? $this->parameters[$matches[1]] : null; } }
  • 86. Template Loaders $loader = new FilesystemLoader(array( '/path/to/project/templates/%name%.php', '/path/to/cms/templates/%name%.php', ));
  • 87. Template Loader Chain $loader = new ChainLoader(array( new ProjectTemplateLoader($pdo), new FilesystemLoader(array( '/path/to/project/templates/%name%.php', '/path/to/cms/templates/%name%.php', )), ));
  • 88. Database Template Loader $pdo = new PDO('sqlite::memory:'); $pdo->exec('CREATE TABLE tpl (name, tpl)'); $pdo->exec('INSERT INTO tpl (name, tpl) VALUES ("articles/ content", "{{ title }} {{ name }}")');
  • 89. Database Template Loader use SymfonyComponentsTemplatingLoaderLoader; class ProjectTemplateLoader extends Loader { protected $pdo; public function __construct($pdo) { $this->pdo = $pdo; } public function load($template, $renderer = 'php') { $stmt = $this->pdo->prepare('SELECT tpl FROM tpl WHERE name = :name'); try { $stmt->execute(array('name' => $template)); if (count($rows = $stmt->fetchAll(PDO::FETCH_NUM))) { return $rows[0][0]; } } catch (PDOException $e) { } return false; } }
  • 90. Template Loader Cache $loader = new CacheLoader($loader, 'path/to/cache');
  • 91. $pdo = new PDO('sqlite::memory:'); $pdo->exec('CREATE TABLE tpl (name, tpl)'); $pdo->exec('INSERT INTO tpl (name, tpl) VALUES ("articles/content", "{{ title }} {{ name }}")'); $loader = new CacheLoader( new ChainLoader(array( new ProjectTemplateLoader($pdo), new FilesystemLoader(array( '/path/to/project/templates/%name%.php', '/path/to/cms/templates/%name%.php', )), )), 'path/to/cache' ); $t = new Engine($loader, array( 'user' => new ProjectTemplateRenderer() )); $t->render('articles/article', array('title' => 'Title', 'content' => 'Lorem...'));
  • 92. Symfony 2 Dependency Injection Container
  • 93. « Dependency Injection is where components are given their dependencies through their constructors, methods, or directly into fields. » http://www.picocontainer.org/injection.html
  • 94. The Symfony 2 dependency injection container replaces several symfony 1 concepts into one integrated system: –  sfContext –  sfConfiguration –  sfConfig –  factories.yml –  settings.yml / logging.yml / i18n.yml –  … and some more
  • 95. DI Hello World example class Message { public function __construct(OutputInterface $output, array $options) { $this->output = $output; $this->options = array_merge(array('with_newline' => false), $options); } public function say($msg) { $this->output->render($msg.($this->options['with_newline'] ? "n" : '')); } }
  • 96. DI Hello World example interface OutputInterface { public function render($msg); } class Output implements OutputInterface { public function render($msg) { echo $msg; } } class FancyOutput implements OutputInterface { public function render($msg) { echo sprintf("033[33m%s033[0m", $msg); } }
  • 97. DI Hello World example $output = new FancyOutput(); $message = new Message($output, array('with_newline' => true)); $message->say('Hello World');
  • 98. A DI container facilitates objects description and object relationships, configures and instantiates objects
  • 99. DI Container Hello World example require __DIR__.'/lib/Symfony/Core/ClassLoader.php'; use SymfonyComponentsDependencyInjectionBuilder; use SymfonyComponentsDependencyInjectionReference; $classLoader = new ClassLoader('Symfony', __DIR__.'/lib'); $classLoader->register(); $container = new Builder(); $container->register('output', 'FancyOutput'); $container-> register('message', 'Message')-> setArguments(array(new Reference('output'), array('with_newline' => true))) ; $container->message->say('Hello World!');
  • 100. $message = $container->message; Get the configuration for the message service The Message constructor must be given an output service Get the output object from the container Create a Message object by passing the constructor arguments
  • 101. $message = $container->message; is roughly equivalent to $output = new FancyOutput(); $message = new Message($output, array('with_newline' => true));!
  • 102. $container = new Builder(); $container->register('output', 'FancyOutput'); $container-> register('message', 'Message')-> setArguments(array(new Reference('output'), array('with_newline' => true))) ; $container->message->say('Hello World!'); PHP <container xmlns="http://symfony-project.org/2.0/container"> <services> <service id="output" class="FancyOutput" /> XML <service id="message" class="Message"> XML is validated <argument type="service" id="output" /> <argument type="collection"> against an XSD <argument key="with_newline">true</argument> </argument> </service> </services> </container> $container = new Builder(); $loader = new XmlFileLoader($container); $loader->load('services.xml');
  • 103. $container = new Builder(); $container->register('output', 'FancyOutput'); $container-> register('message', 'Message')-> setArguments(array(new sfServiceReference('output'), array('with_newline' => true))) ; $container->message->say('Hello World!'); PHP services: output: { class: FancyOutput } message: YAML class: Message arguments: - @output - { with_newline: true } $container = new Builder(); $loader = new YamlFileLoader($container); $loader->load('services.yml');
  • 104. <container xmlns="http://symfony-project.org/2.0/container"> <parameters> <parameter key="output.class">FancyOutput</parameter> <parameter key="message.options" type="collection"> <parameter key="with_newline">true</parameter> </parameter> </parameters> <services> <service id="output" class="%output.class%" /> <service id="message" class="Message"> <argument type="service" id="output" /> <argument>%message.options%</argument> </service> </services> </container> $container = new rBuilder(); $loader = new XmlFileLoader($container); $loader->load('services.xml');
  • 105. <container xmlns="http://symfony-project.org/2.0/container"> <imports> <import resource="config.xml" /> </imports> <services> <service id="output" class="%output.class%" /> <service id="message" class="Message"> <argument type="service" id="output" /> <argument>%message.options%</argument> </service> </services> </container> <container xmlns="http://symfony-project.org/2.0/container"> <parameters> <parameter key="output.class">FancyOutput</parameter> <parameter key="message.options" type="collection"> <parameter key="with_newline">true</parameter> </parameter> </parameters> </container> $container = new Builder(); $loader = new FileXmlFileLoader($container); $loader->load('services.xml');
  • 106. <services> <import resource="config.yml" class="SymfonyComponentsDependencyInjectionLoader YamlFileLoader" /> <service id="output" class="%output.class%" /> <service id="message" class="Message"> <argument type="service" id="output" /> <argument>%message.options%</argument> </service> </services> parameters: output.class: FancyOutput message.options: { with_newline: true } $container = new Builder(); $loader = new XmlFileLoader($container); $loader->load('services.xml');
  • 107. $pdo = new PDO('sqlite::memory:'); $pdo->exec('CREATE TABLE tpl (name, tpl)'); $pdo->exec('INSERT INTO tpl (name, tpl) VALUES ("articles/content", "{{ title }} {{ name }}")'); $loader = new CacheLoader( new ChainLoader(array( new ProjectTemplateLoader($pdo), new FilesystemLoader(array( '/path/to/project/templates/%name%.php', '/path/to/cms/templates/%name%.php', )), )), 'path/to/cache' ); $t = new Engine($loader, array( 'user' => new ProjectTemplateRenderer() )); $t->render('articles/article', array('title' => 'Title', 'content' => 'Lorem...'));
  • 108. $pdo = new PDO('sqlite::memory:'); <service id="pdo" class="PDO"> <argument>sqlite::memory:</argument> </service>
  • 109. $container = new Builder(); $loader = new FileXmlLoader($container); $loader->load('cms.xml'); $pdo->exec('CREATE TABLE tpl (name, tpl)'); $pdo->exec('INSERT INTO tpl (name, tpl) VALUES ("articles/content", "{{ title }} {{ name }}")'); echo $container->template->render('articles/article', array('title' => 'Title', 'content' => 'Lorem...'));
  • 110. <container xmlns="http://symfony-project.org/2.0/container"> <imports> <import resource="config.yml" class="SymfonyComponentsDependencyInjectionLoader YamlFileLoader" /> <import resource="template_loader.xml" /> </imports> <services> <service id="pdo" class="PDO"> <argument>sqlite::memory:</argument> </service> <service id="template_renderer" class="ProjectTemplateRenderer" /> <service id="template" class="SymfonyComponentsTemplatingEngine"> <argument type="service" id="template_loader" /> <argument type="collection"> <argument type="service" key="user" id="template_renderer" /> </argument> </service> </services> </container>
  • 111. <services> <service id="template_loader_project" class="ProjectTemplateLoader"> <argument type="service" key="pdo" id="pdo" /> </service> <service id="template_loader_filesystem" class="SymfonyComponentsTemplatingLoader FilesystemLoader"> <argument>%template.filesystem_pattern%</argument> </service> <service id="template_loader_chain" class="SymfonyComponentsTemplatingLoaderChainLoader"> <argument type="collection"> <argument type="service" id="template_loader_project" /> <argument type="service" id="template_loader_filesystem" /> </argument> </service> <service id="template_loader" class="SymfonyComponentsTemplatingLoaderCacheLoader"> <argument type="service" id="template_loader_chain" /> <argument>%application.dir%/cache</argument> </service> </services>
  • 112. <services> <service id="template_loader" class="SymfonyComponentsTemplatingLoaderCacheLoader"> <argument type="service"> <service class="SymfonyComponentsTemplatingLoaderChainLoader"> <argument type="collection"> <argument type="service"> <service class="ProjectTemplateLoader"> <argument type="service" key="pdo" id="pdo" /> </service> </argument> <argument type="service"> <service class="SymfonyComponentsTemplatingLoaderFilesystemLoader"> <argument>%template.filesystem_patterns%</argument> </service> </argument> </argument> </service> </argument> <argument>%application.dir%/cache</argument> </service> </services>
  • 113. partners.sensiolabs.com •  SITE PARTNERS Coming soon… Contact me if you are interested
  • 114. symfony-live.com with Matthew Weier O’Pheinney I will reveal the first alpha release of Symfony 2!
  • 115. symfony-live.com with Matthew Weier O’Pheinney and with Matthew Weier O'Phinney as a special guest
  • 116. Questions?
  • 117. Sensio S.A. 92-98, boulevard Victor Hugo 92 115 Clichy Cedex FRANCE Tél. : +33 1 40 99 80 80 Contact Fabien Potencier fabien.potencier at sensio.com http://www.sensiolabs.com/ http://www.symfony-project.org/ http://fabien.potencier.org/