• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Symfony2 revealed
 

Symfony2 revealed

on

  • 38,311 views

Symfony2 revealed

Symfony2 revealed

Statistics

Views

Total Views
38,311
Views on SlideShare
23,274
Embed Views
15,037

Actions

Likes
54
Downloads
681
Comments
0

72 Embeds 15,037

http://www.scoop.it 4203
http://php5.phpmagazine.net 2377
http://www.symfony.es 2278
http://www.symfonylab.com 1518
http://t3n.de 1079
http://blog.goyello.com 863
http://vincent.composieux.fr 439
http://www.symfony-project.org 379
http://www.zalas.pl 337
http://symfony.com 323
http://www.slideshare.net 134
http://francescoagati.wordpress.com 129
http://swik.net 127
http://www.phpmagazine.net 120
http://www.ciudadperdida.org 117
http://www.netlash.com 103
http://www.alpict.com 58
http://sf.composieux.fr 50
http://symfony.es 47
http://blog.local 41
http://journal.lerouxdelens.com 33
http://feeds.feedburner.com 30
http://code.saigonbrand.com 30
http://dbertinat.blogspot.com 23
http://phpmagazine.net 21
https://www.socialappshq.com 17
http://translate.googleusercontent.com 17
http://wiki.ideotechnologies.com 14
http://webcache.googleusercontent.com 13
http://www.socialappshq.com 13
http://www.php.rk.edu.pl 11
http://www.online-studeren.net 9
http://paper.li 7
http://demo.apostrophenow.com 6
http://m.phpmagazine.net 6
http://www.phpframeworks.com 5
http://dbertinat.blogspot.com.es 5
http://a0.twimg.com 4
http://www.iweb34.com 4
http://grameen.skipso.eu 4
http://www.symfolive.com 3
http://static.slidesharecdn.com 3
http://www.online-translator.com 2
http://88.191.134.37 2
http://allphp.com 2
http://aulavirtual.usmpvirtual.edu.pe 2
http://jiewmeng.tumblr.com 2
http://1992071871.nvmodules.netvibes.com 2
http://pt.minichiello.name 2
http://1991183613.nvmodules.netvibes.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

    Symfony2 revealed Symfony2 revealed Presentation Transcript

    • Fabien Potencier
    • A bit of history
    • 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, …
    • symfony 1.2 – November 2008 •  Based on decoupled but cohesive components –  Forms, Routing, Cache, YAML, ORMs, … •  Controller still based on Mojavi –  View, Filter Chain, …
    • symfony 1.4 – November 2009 •  Added some polish on existing features •  Removed the support for deprecated features •  Current LTS release, maintained until late 2012
    • Symfony Components YAML Dependency Injection Container Event Dispatcher Templating Routing Console Output Escaper Request Handler …
    • What is Symfony 2?
    • Symfony 2 is the next version of the symfony framework… except Symfony now takes a S instead of a s
    • Talk about Symfony 2 or symfony 1
    • To make it clear: Symfony 1 does not make any sense
    • symfony 2 does not make more sense
    • Symfony 2
    • Same philosophy, just better
    • MVC
    • hmmm, now that I think about it…
    • …it’s now probably more a Fabien’s style framework than anything else
    • Highly configurable Highly extensible Same Symfony Components Same great developer tools Full-featured
    • Ok, but why a major version then?
    • Symfony 2 has a brand new low-level architecture
    • PHP 5.3
    • A Quick Tour
    • <?php require_once __DIR__.'/../blog/BlogKernel.php'; $kernel = new BlogKernel('prod', false); $kernel->run();
    • <?php Everything is namespaced namespace ApplicationHelloBundleController; use SymfonyFrameworkWebBundleController; class HelloController extends Controller { public function indexAction($name) Variables come from the routing { return $this->render('HelloBundle:Hello:index', array('name' => $name)); } } Template name Variables to pass to the template
    • Layout <?php $view->extend('HelloBundle::layout') ?> Hello <?php echo $name ?>!
    • <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <?php $view->slots->output('_content') ?> </body> </html> Helpers are objects
    • hello: pattern: /hello/:name defaults: _bundle: HelloBundle _controller: Hello _action: index
    • hello: pattern: /hello/:name defaults: _bundle: HelloBundle _controller: Hello _action: index namespace ApplicationHelloBundleController; class HelloController extends Controller { public function indexAction($name) { // ... } }
    • hello: pattern: /hello/:name defaults: _bundle: HelloBundle _controller: Hello _action: index namespace ApplicationHelloBundleController; class HelloController extends Controller { public function indexAction($name) { // ... } }
    • hello: pattern: /hello/:name defaults: _bundle: HelloBundle _controller: Hello _action: index namespace ApplicationHelloBundleController; class HelloController extends Controller { public function indexAction($name) { // ... } }
    • hello: pattern: /hello/:name defaults: _bundle: HelloBundle _controller: Hello _action: index namespace ApplicationHelloBundleController; class HelloController extends Controller { public function indexAction($name) { // ... } }
    • hello: pattern: /hello/:name defaults: _bundle: HelloBundle _controller: Hello _action: index namespace ApplicationHelloBundleController; class HelloController extends Controller { public function indexAction($name) { // ... } }
    • hello: pattern: /hello/:year/:month/:slug defaults: _bundle: HelloBundle _controller: Hello _action: index namespace ApplicationHelloBundleController; class HelloController extends Controller { public function indexAction($slug, $year) { // ... } }
    • Extremely Configurable
    • Dependency Injection Container
    • Replaces a lot of symfony 1 “things” sfConfig All config handlers sfProjectConfiguration / sfApplicationConfiguration sfContext (No Singleton anymore) The configuration cache system … and some more
    • in one easy-to-master unified and cohesive package
    • Thanks to the DIC, Configuration has never been so easy and so flexible
    • Name your configuration files the way you want
    • Store them where you want
    • Use PHP, XML, YAML, or INI
    • $configuration = new BuilderConfiguration(); $configuration->addResource(new FileResource(__FILE__)); $configuration ->mergeExtension('web.user', array('default_culture' => 'fr', 'session' => array('name' => 'SYMFONY', 'type' => 'Native', 'lifetime' => 3600))) ->mergeExtension('doctrine.dbal', array('dbname' => 'sfweb', 'username' => 'root')) ->mergeExtension('web.templating', array('escaping' => 'htmlspecialchars', 'assets_version' => 'SomeVersionScheme')) ->mergeExtension('swift.mailer', array('transport' => 'gmail', 'username' => 'fabien.potencier', 'password' => 'xxxxxx')) PHP   ;
    • web.user: default_culture: fr session: { name: SYMFONY, type: Native, lifetime: 3600 } web.templating: escaping: htmlspecialchars assets_version: SomeVersionScheme doctrine.dbal: { dbname: sfweb, username: root, password: null } swift.mailer: transport: gmail username: fabien.potencier password: xxxxxxxx YAML  
    • <web:user default_culture="fr"> <web:session name="SYMFONY" type="Native" lifetime="3600" /> </web:user> <web:templating escaping="htmlspecialchars" assets_version="SomeVersionScheme" /> <doctrine:dbal dbname="sfweb" username="root" password="" /> <swift:mailer transport="gmail" username="fabien.potencier" password="xxxxxxxx" /> XML  
    • $configuration->mergeExtension('swift.mailer', array( 'transport' => 'gmail', 'username' => 'fabien.potencier', 'password' => 'xxxxxx', )); PHP  
    • swift.mailer: transport: gmail username: fabien.potencier password: xxxxxxxx YAML  
    • <swift:mailer transport="gmail" username="fabien.potencier" password="xxxxxxxx" /> XML  
    • <?xml version="1.0" ?> <container xmlns="http://www.symfony-project.org/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance » xmlns:doctrine="http://www.symfony-project.org/schema/dic/doctrine" xmlns:zend="http://www.symfony-project.org/schema/dic/zend" xmlns:swift="http://www.symfony-project.org/schema/dic/swiftmailer" > XML  
    • <?xml version="1.0" ?> <container xmlns="http://www.symfony-project.org/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance » xmlns:doctrine="http://www.symfony-project.org/schema/dic/doctrine" xmlns:zend="http://www.symfony-project.org/schema/dic/zend" xmlns:swift="http://www.symfony-project.org/schema/dic/swiftmailer" xsi:schemaLocation="http://www.symfony-project.org/schema/dic/services http://www.symfony-project.org/schema/dic/services/services-1.0.xsd http://www.symfony-project.org/schema/dic/doctrine http://www.symfony-project.org/schema/dic/doctrine/doctrine-1.0.xsd http://www.symfony-project.org/schema/dic/zend http:// www.symfony-project.org/schema/dic/zend/zend-1.0.xsd http://www.symfony-project.org/schema/dic/swiftmailer http://www.symfony-project.org/schema/dic/swiftmailer/swiftmailer-1.0.xsd »> XML  
    • Inherit them as much as you want
    • Mix and match configuration files written in any format useful when using third-party plugins
    • <imports> <import resource="parent.xml" /> <import resource="config.yml" /> Mix and match formats <import resource="parameters.ini" /> </imports> <zend:logger priority="debug" path="%kernel.logs_dir%/%kernel.environment%.log" /> <web:debug exception="%kernel.debug%" toolbar="%kernel.debug%" ide="textmate" />
    • You choose the format you want Pros Cons XML validation verbose (not that much) IDE completion & help YAML concise needs the YAML component simple to read no validation easy to change no IDE auto-completion PHP flexible no validation more expressive
    • Store sensitive settings outside of your project
    • <doctrine:dbal dbname="sfweb" username="root" password="SuperSecretPasswordThatAnyoneCanSee" />
    • in a .htaccess or httpd.conf file SetEnv SYMFONY__DOCTRINE__DBAL__PASSWORD "foobar" %doctrine.dbal.password%
    • Semantic Configuration
    • <swift:mailer transport="gmail" username="fabien.potencier" password="xxxxxxxx" /> XML  
    • <swift:mailer transport="smtp" encryption="ssl" auth_mode="login" host="smtp.gmail.com" username="fabien.potencier" password="xxxxxxxx" /> XML  
    • <parameters> <parameter key="swiftmailer.class">Swift_Mailer</parameter> <parameter key="swiftmailer.transport.smtp.class">Swift_Transport_EsmtpTransport</parameter> <parameter key="swiftmailer.transport.smtp.host">smtp.gmail.com</parameter> <parameter key="swiftmailer.transport.smtp.port">25</parameter> <parameter key="swiftmailer.transport.smtp.encryption">ssl</parameter> <parameter key="swiftmailer.transport.smtp.username">fabien.potencier</parameter> <parameter key="swiftmailer.transport.smtp.password">xxxxxx</parameter> <parameter key="swiftmailer.transport.smtp.auth_mode">login</parameter> <parameter key="swiftmailer.init_file">swift_init.php</parameter> </parameters> <services> <service id="swiftmailer.mailer" class="%swiftmailer.class%"> <argument type="service" id="swiftmailer.transport" /> <file>%swiftmailer.init_file%</file> </service> <service id="swiftmailer.transport.smtp" class="%swiftmailer.transport.smtp.class%"> <argument type="service" id="swiftmailer.transport.buffer" /> <argument type="collection"> <argument type="service" id="swiftmailer.transport.authhandler" /> </argument> <argument type="service" id="swiftmailer.transport.eventdispatcher" /> <call method="setHost"><argument>%swiftmailer.transport.smtp.host%</argument></call> <call method="setPort"><argument>%swiftmailer.transport.smtp.port%</argument></call> <call method="setEncryption"><argument>%swiftmailer.transport.smtp.encryption%</argument></call> <call method="setUsername"><argument>%swiftmailer.transport.smtp.username%</argument></call> <call method="setPassword"><argument>%swiftmailer.transport.smtp.password%</argument></call> <call method="setAuthMode"><argument>%swiftmailer.transport.smtp.auth_mode%</argument></call> </service> <service id="swiftmailer.transport.buffer" class="Swift_Transport_StreamBuffer"> <argument type="service" id="swiftmailer.transport.replacementfactory" /> </service> <service id="swiftmailer.transport.authhandler" class="Swift_Transport_Esmtp_AuthHandler"> <argument type="collection"> <argument type="service"><service class="Swift_Transport_Esmtp_Auth_CramMd5Authenticator" /></argument> <argument type="service"><service class="Swift_Transport_Esmtp_Auth_LoginAuthenticator" /></argument> <argument type="service"><service class="Swift_Transport_Esmtp_Auth_PlainAuthenticator" /></argument> </argument> XML   </service> <service id="swiftmailer.transport.eventdispatcher" class="Swift_Events_SimpleEventDispatcher" /> <service id="swiftmailer.transport.replacementfactory" class="Swift_StreamFilters_StringReplacementFilterFactory" /> <service id="swiftmailer.transport" alias="swiftmailer.transport.smtp" /> </services>
    • Creating DIC extensions is insanely simple
    • Very Fast thanks to a Smart Caching mechanism it always knows when to flush the cache
    • /** * Gets the 'swiftmailer.mailer' service. * * This service is shared. * This method always returns the same instance of the service. * * @return Swift_Mailer A Swift_Mailer instance. PHPDoc for auto-completion */ protected function getSwiftmailer_MailerService() { if (isset($this->shared['swiftmailer.mailer'])) return $this->shared['swiftmailer.mailer']; As fast as it could be $instance = new Swift_Mailer($this->getSwiftmailer_Transport_SmtpService()); return $this->shared['swiftmailer.mailer'] = $instance; }
    • The DIC can manage ANY PHP object (POPO)
    • Plugins…
    • or Bundles
    • Plugins are first-class citizens They are called Bundles
    • Everything is a bundle Core features Third-party code Application code
    • app/ src/ web/
    • app/ AppKernel.php cache/ config/ console logs/
    • src/ autoload.php Application/ Bundle/ vendor/ doctrine/ swiftmailer/ symfony/ zend/
    • web/ index.php index_dev.php
    • .../ SomeBundle/ Bundle.php Controller/ Model/ Resources/ config/ views/
    • public function registerBundleDirs() { return array( 'Application' => __DIR__.'/../src/Application', 'Bundle' => __DIR__.'/../src/Bundle', 'SymfonyFramework' => __DIR__.'/../src/vendor/ symfony/src/Symfony/Framework', ); }
    • $this->render('SomeBundle:Hello:index', $params)
    • hello: pattern: /hello/:name defaults: { _bundle: SomeBundle, ... }
    • SomeBundle can be any of ApplicationSomeBundle BundleSomeBundle SymfonyFrameworkSomeBundle
    • Less concepts… but more powerful ones
    • symfony 1 View Layer templates layouts slots components partials component slots
    • Symfony 2 View Layer templates slots
    • A layout is just another template with _content as a special slot A partial is just a template you embed in another one A component is just another action embedded in a template
    • <?php $view->output('BlogBundle:Post:list', array('posts' => $posts)) ?>
    • <?php $view->actions->output('BlogBundle:Post:list', array ('limit' => 2)) ?>
    • <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <?php $view->slots->output('_content') ?> </body> </html>
    • Big and Small Improvements
    • multiple level of layouts
    • partials can be decorated!
    • Better Logs
    • INFO: Matched route "blog_home" (parameters: array ( '_bundle' => 'BlogBundle', '_controller' => 'Post', '_action' => 'index', '_route' => 'blog_home',)) INFO: Using controller "BundleBlogBundleController PostController::indexAction" INFO: SELECT s0_.id AS id0, s0_.title AS title1, s0_.html_body AS html_body2, s0_.excerpt AS excerpt3, s0_.published_at AS published_at4 FROM sf_weblog_post s0_ ORDER BY s0_.published_at DESC LIMIT 10 (array ())
    • INFO: Matched route "blog_post" (parameters: array ( '_bundle' => 'BlogBundle', '_controller' => 'Post', '_action' => 'show', '_format' => 'html', 'id' => '3456', '_route' => 'blog_post',)) INFO: Using controller "BundleBlogBundleController PostController::showAction » INFO: SELECT s0_.id AS id0, s0_.title AS title1, s0_.html_body AS html_body2, s0_.excerpt AS excerpt3, s0_.published_at AS published_at4 FROM sf_weblog_post s0_ WHERE s0_.id = ? (array ( 0 => '3456',)) ERR: Post "3456" not found! (No result was found for query although at least one row was expected.) (uncaught SymfonyComponentsRequestHandlerException NotFoundHttpException exception) INFO: Using controller "SymfonyFrameworkWebBundleController ExceptionController::exceptionAction"
    • <zend:logger priority="debug" />
    • DEBUG: Notifying (until) event "core.request" to listener "(SymfonyFrameworkWebBundleListenerRequestParser, resolve)" INFO: Matched route "blog_post" (parameters: array ( '_bundle' => 'BlogBundle', '_controller' => 'Post', '_action' => 'show', '_format' => 'html', 'id' => '3456', '_route' => 'blog_post',)) DEBUG: Notifying (until) event "core.load_controller" to listener "(SymfonyFrameworkWebBundleListenerControllerLoader, resolve)" INFO: Using controller "BundleBlogBundleControllerPostController::showAction" DEBUG: Listener "(SymfonyFrameworkWebBundleListenerControllerLoader, resolve)" processed the event "core.load_controller" INFO: Trying to get post "3456" from database INFO: SELECT s0_.id AS id0, s0_.title AS title1, s0_.html_body AS html_body2, s0_.excerpt AS excerpt3, s0_.published_at AS published_at4 FROM sf_weblog_post s0_ WHERE s0_.id = ? (array ( 0 => '3456',)) DEBUG: Notifying (until) event "core.exception" to listener "(SymfonyFrameworkWebBundleListenerExceptionHandler, handle)" ERR: Post "3456" not found! (No result was found for query although at least one row was expected.) (uncaught SymfonyComponents RequestHandlerExceptionNotFoundHttpException exception) DEBUG: Notifying (until) event "core.request" to listener "(SymfonyFrameworkWebBundleListenerRequestParser, resolve)" DEBUG: Notifying (until) event "core.load_controller" to listener "(SymfonyFrameworkWebBundleListenerControllerLoader, resolve)" INFO: Using controller "SymfonyFrameworkWebBundleControllerExceptionController::exceptionAction" DEBUG: Listener "(SymfonyFrameworkWebBundleListenerControllerLoader, resolve)" processed the event "core.load_controller" DEBUG: Notifying (filter) event "core.response" to listener "(SymfonyFrameworkWebBundleListenerResponseFilter, filter)" DEBUG: Notifying (filter) event "core.response" to listener "(SymfonyFrameworkWebBundleDebugDataCollector DataCollectorManager, handle)" DEBUG: Notifying (filter) event "core.response" to listener "(SymfonyFrameworkWebBundleDebugWebDebugToolbar, handle)" DEBUG: Listener "(SymfonyFrameworkWebBundleListenerExceptionHandler, handle)" processed the event "core.exception" DEBUG: Notifying (filter) event "core.response" to listener "(SymfonyFrameworkWebBundleListenerResponseFilter, filter)" DEBUG: Notifying (filter) event "core.response" to listener "(SymfonyFrameworkWebBundleDebugDataCollector DataCollectorManager, handle)" DEBUG: Notifying (filter) event "core.response" to listener "(SymfonyFrameworkWebBundleDebugWebDebugToolbar, handle)"
    • Even Better Exception Error Pages
    • An Event Better Web Debug Toolbar
    • Everything you need is at the bottom of the screen
    • Web Designer “friendly”
    • app/ views/ BlogBundle/ Post/ index.php AdminGeneratorBundle/ DefaultTheme/ list.php edit.php ...
    • “Mount” Routing Configuration
    • blog: resource: BlogBundle/Resources/config/routing.yml forum: resource: ForumBundle/Resources/config/routing.yml prefix: /forum
    • Symfony 2 is a lazy framework
    • Smart Autoloading
    • require_once __DIR__.'/vendor/symfony/src/Symfony/Foundation/UniversalClassLoader.php'; use SymfonyFoundationUniversalClassLoader; $loader = new UniversalClassLoader(); $loader->registerNamespaces(array( 'Symfony' => __DIR__.'/vendor/symfony/src', 'Application' => __DIR__, 'Bundle' => __DIR__, 'Doctrine' => __DIR__.'/vendor/doctrine/lib', )); $loader->registerPrefixes(array( 'Swift_' => __DIR__.'/vendor/swiftmailer/lib/classes', 'Zend_' => __DIR__.'/vendor/zend/library', )); $loader->register(); // for Zend Framework & SwiftMailer set_include_path(__DIR__.'/vendor/zend/library'.PATH_SEPARATOR.__DIR__.'/vendor/ swiftmailer/lib'.PATH_SEPARATOR.get_include_path());
    • lazy-loading of services
    • lazy-loading of listeners
    • lazy-loading of helpers
    • <?php echo $view->router->generate('blog_post', array('id' => $post->getId())) ?>
    • Symfony 2 is a “cachy” framework
    • blog/ cache/ prod/ blogProjectContainer.php blogUrlGenerator.php blogUrlMatcher.php classes.php
    • class blogUrlMatcher extends SymfonyComponentsRoutingMatcherUrlMatcher { public function __construct(array $context = array(), array $defaults = array()) { $this->context = $context; $this->defaults = $defaults; } public function match($url) { $url = $this->normalizeUrl($url); if (0 === strpos($url, '/webblog') && preg_match('#^/webblog/(? P<id>[^/.]+?)$#x', $url, $matches)) return array_merge($this->mergeDefaults($matches, array ( '_bundle' => 'WebBundle', '_controller' => 'Redirect', '_action' => 'redirect', 'route' => 'blog_post',)), array('_route' => 'old_blog_post_redirect'));
    • You can use Apache for Routing matching
    • A Very Fast Dev. Env.
    • blog/ cache/ dev/ blogProjectContainer.meta blogProjectContainer.php blogUrlGenerator.meta blogUrlGenerator.php blogUrlMatcher.meta blogUrlMatcher.php classes.meta classes.php prod/ blogProjectContainer.php blogUrlGenerator.php blogUrlMatcher.php classes.php
    • Symfony 2
    • Easy to learn Easy to use Extensible at will
    • Easy to learn Easy to use
    • Extensible at will
    • But Symfony 2 should be slow, right?
    • Fast as hell
    • Benchmark on a simple application
    • 2x faster than Solar 1.0.0
    • 2.5x faster than symfony 1.4.2
    • 3x faster than Zend Framework 1.10
    • 4x faster than Lithium
    • 6x faster than CakePHP 1.2.6
    • 60x faster than Flow3
    • …and Symfony 2.0 uses half the memory needed by both symfony 1 and ZF
    • We have barely scratched the surface of all the goodness of Symfony 2.0
    • Controller except for the nice default pages Autoloading Cache via ZF - DI extension coming soon CLI commands still missing Configuration Database via Doctrine DBAL Debug except Timer and extended WDT Escaper Event Dispatcher Form / Validation / Widget can use the 1.4 version as is Admin Generator Helpers I18n / L10n can use the 1.4 version as is Logger via ZF Mailer except commands Bundles except installing Doctrine Plugin just the DBAL part Propel Plugin Request / Response Routing no REST support, no Object support Storage / User Test View
    • Final Release Target Date Late 2010
    • If you want the bleeding edge of news, follow me on Twitter @fabpot on Github github.com/fabpot
    • http://symfony-reloaded.org/
    • Questions? My slides will be available on http://slideshare.com/fabpot
    • 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/