• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Symfony2 from the Trenches
 

Symfony2 from the Trenches

on

  • 18,088 views

Symfony2 from the Trenches presentation at Symfony Live 2011

Symfony2 from the Trenches presentation at Symfony Live 2011

Statistics

Views

Total Views
18,088
Views on SlideShare
11,802
Embed Views
6,286

Actions

Likes
21
Downloads
167
Comments
0

84 Embeds 6,286

http://www.lafermeduweb.net 2409
http://devtime.blogspot.com 1765
http://www.symfony-project.org 475
http://symfony2tips.blogspot.com 276
http://swik.net 220
http://www.symfony.es 213
http://blogdwich.fr 136
http://symfony.com 130
http://gpupo.com 90
http://devtime.blogspot.fr 60
http://test.ical.ly 53
http://devtime.blogspot.ru 43
http://devtime.blogspot.de 36
http://devtime.blogspot.co.uk 21
http://devtime.blogspot.in 21
http://devtime.blogspot.it 20
http://devtime.blogspot.com.br 19
http://static.slidesharecdn.com 17
http://devtime.blogspot.com.ar 15
http://www.emmanuelpereira.com 15
http://devtime.blogspot.com.es 14
http://devtime.blogspot.ca 14
http://webcache.googleusercontent.com 14
http://rimzy.net 13
http://coderwall.com 11
http://symfony2tips.blogspot.fr 10
http://symfony2tips.blogspot.co.uk 9
http://devtime.blogspot.nl 7
http://www.testically.org 7
http://symfony2tips.blogspot.de 7
http://devtime.blogspot.jp 7
http://www.sfexception.com 7
http://devtime.blogspot.se 6
http://devtime.blogspot.hu 6
http://feeds.feedburner.com 6
http://www.techgig.com 6
http://devtime.blogspot.cz 6
http://devtime.blogspot.co.il 5
http://symfony2tips.blogspot.com.br 5
http://devtime.blogspot.com.au 5
http://symfony2tips.blogspot.pt 5
http://devtime.blogspot.pt 5
http://symfony2tips.blogspot.in 5
http://translate.googleusercontent.com 5
http://symfony2tips.blogspot.com.es 3
http://devtime.blogspot.be 3
http://xss.yandex.net 3
http://devtime.blogspot.mx 3
http://matmati.net 3
http://devtime.blogspot.co.at 3
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 from the Trenches Symfony2 from the Trenches Presentation Transcript

    • Symfony2 - From the Trenches by Lukas Kahwe Smith, Kris Wallsmith, Thibault Duplessis, Jeremy Mikola, Jordi Boggiano, Jonathan H. Wage, Bulat Shakirzyanov
    • AgendaGetting Setup CachingCode Flow Performance TipsDependency Injection Asset ManagementConfiguration Choices TestingController Choices DeploymentApplication Choices Third Party BundlesDoctrine Resources
    • Getting the works)PHP 5.3+ with ext/intl (compat lib is in setup Read check.php for details (dev/prod php.inis from Liip) Using OSX? php53-intl from liangzhenjing or build-entropy-php from chregu Blog post on installing PHP 5.3 with intl from Justin HilemanInitial setup symfony-sandbox symfony-bootstrap Symfony2ProjectRead the Coding Style Guide (Code Sniffer Rules)Managing external dependencies Submodule: not everything is in git (svn, mercurial, etc.) Vendor install/update scripts: risk of getting out of sync MR (not cross platform)
    • Code Flow1. Frontend Controller (web/app[_dev].php) Loads autoloader Creates/boots kernel Creates request (from globals) and passes to kernel2. Kernel Loads app config (app/config/config_[prod|dev|test]) Resolves URL path to a controller (go to 3.) Outputs response returned by the controller3. Controller Loads model and view Potentially creates a sub-request (go to 2.) Creates response and returns it
    • Execution Flow
    • Dependency InjectionAll objects are instantiated in one of two ways: Using the "new" operator Using an object factoryAll objects get collaborators in one of two ways Passed to object constructor Set using a setter
    • Application Using Dependency Injection
    • <?xml version="1.0" encoding="utf-8" ?><container xmlns="http://www.symfony-project.org/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <parameters> <parameter key="sitemap.class">BundleAvalancheSitemapBundleSitemap</parameter> </parameters> <services> <service id="sitemap" class="%sitemap.class%" /> </services></container> Describe Your Services
    • <?phpclass cachedDevDebugProjectContainer extends Container{ /** * Gets the sitemap service. * * @return BundleAvalancheSitemapBundleSitemap */ protected function getSitemapService() { return $this->services[sitemap] = new BundleAvalancheSitemapBundleSitemap(); } /** * Gets the default parameters. * * @return array An array of the default parameters */ protected function getDefaultParameters() { return array( sitemap.class => BundleAvalancheSitemapBundleSitemap ); }} Service Definitions Are Dumped to Raw PHP
    • Dependency Injection ContainerBenefits: No performance loss Lazy instantiation Readable service configurationsGotchas: Can become hard to work with if the DI extension tries to do too much Be aware of circular dependencies Might lead to code that cannot be used outside of DIC
    • Circular Dependency Example
    • <?phpclass SomeClass{ private $container; public function __construct(ContainerInterface $container) <service id="some_service" class="SomeClass"> { <argument type="service" id="service_container" /> $this->container = $container; </service> } <!-- or --> // or <service id="some_service" class="SomeClass"> public function setContainer(ContainerInterface $container) <call method="setContainer"> { <argument type="service" id="service_container" /> $this->container = $container; </call> } </service> public function getDocumentManager() { return $this->container->get(document_manager); }} Container Injection
    • <?phpclass SomeClass{ private $documentManager; public function __construct(DocumentManager $documentManager) { $this->documentManager = $documentManager; } public function getDocumentManager() { return $this->documentManager; }}<service id="some_service" class="SomeClass"> <argument type="service" id="document_manager" /></service> Constructor Injection
    • <?phpclass SomeClass{ private $documentManager; public function setDocumentManager(DocumentManager $documentManager) { $this->documentManager = $documentManager; } public function getDocumentManager() { return $this->documentManager; }}<service id="some_service" class="SomeClass"> <call method="setDocumentManager"> <argument type="service" id="document_manager" /> </call></service> Setter Injection
    • <?phpinterface SomeInterface{ function setDocumentManager(DocumentManager $documentManager);}class SomeClass implements SomeInterface{ private $documentManager; public function setDocumentManager(DocumentManager $documentManager) { $this->documentManager = $documentManager; } public function getDocumentManager() { return $this->documentManager; }}<interface id="some_service" class="SomeInterface"> <call method="setDocumentManager"> <argument type="service" id="document_manager" /> </call></interface><service id="some_service" class="SomeClass" /> Interface Injection
    • Configuration ChoicesSymfony supports XML, YAML and PHP for configurationYAML and PHP uses underscore to separate wordsXML uses dashes to separate wordsXML attributes usually map to array values for YAML/PHPYAML merge key syntax to reuse pieces within a fileXSD-aware editors provide auto-completion and validationXML is recommended for Bundle/DI configurationYAML is recommended for application configurationDoctrine does not like it when you mix formats!
    • Controller ChoicesDefining Controllers as services is optional Non-service controllers must use container injection Create a Bundle Extension to load Bundle servicesIts recommended to not extend from the base Controller The base controller is mainly a tool for beginners It provides convenience methods that invoke services generateUrl(), redirect(), render()
    • Application ChoicesSecurity system makes it possible to have just oneapplication for both frontend and admin backendLocation of application is totally flexible, just update thefrontend controllers accordinglyLarge projects should use multiple applications Better separation when multiple teams work Facilitate step-by-step updating and refactoring For example: main, mobile, API, admin
    • Doctrine ExamplesRetrieve references to entity/document without DB queriesUsing raw SQL queries with Doctrine2 ORMSimple search engine with Doctrine MongoDB ODM
    • Retrieving References w/o DB Queries$tags = array(baseball, basketball);foreach ($tags as $tag) { $product->addTag($em->getReference(Tag, $tag));}
    • Raw SQL Queries$rsm = new ResultSetMapping;$rsm->addEntityResult(User, u);$rsm->addFieldResult(u, id, id);$rsm->addFieldResult(u, name, name);$query = $this->_em->createNativeQuery(SELECT id, nameFROM users WHERE name = ?, $rsm);$query->setParameter(1, romanb);$users = $query->getResult();http://www.doctrine-project.org/docs/orm/2.0/en/reference/native-sql.html
    • Simple Search Engineinterface HasKeywords{ function setKeywords(); function getKeywords();}
    • Simple Search Engine/** @mongodb:EmbeddedDocument */class Keyword{ // ... /** @mongodb:String @mongodb:Index */ private $keyword; /** @mongodb:Integer */ private $score; // ...}
    • Simple Search Engine/** @mongodb:Document */class Product implements HasKeywords{ /** @mongodb:Id */ private $id; /** @mongodb:String */ private $title; /** @mongodb:EmbedMany(targetDocument="Keyword") */ private $keywords = array(); // ...}
    • Simple Search Engineclass KeywordListener{ public function preUpdate(PreUpdateEventArgs $eventArgs) { $entity = $eventArgs->getEntity(); if ($entity instanceof HasKeywords) { $entity->setKeywords($this->buildKeywords($entity)); } } private function buildKeywords(HasKeywords $entity) { $keywords = array(); // build keywords from title, description, etc. return $keywords; }}
    • Simple Search Engine// find products by keyword$products = $dm->createQueryBuilder() ->field(keywords.keyword)->all($keywords) ->getQuery() ->execute();
    • Different Content Areas of a Page
    • Caching with Edge Side IncludesSymfony2 provides support for Edge Side Includes (ESI) Proxy assembles page from snippets of HTML Snippets can have different cache rules Develop without ESI, test with Symfony2 internal ESI proxy, deploy using ultra fast Varnish ProxyBreak up page into different controller actions based oncache invalidation rules Do not worry about overhead from multiple render calls Never mix content that has different cache timeouts Varnish Reverse Proxy Super fast, PHP cannot touch the performance Cache full pages for anonymous users Not just for HTML, also useful for JSON/XML API
    • Page Rendered Behind a Reverse Proxy
    • Performance TipsDump routes to apache rewrite rulesCache warmingDo not add optional services to controllersDo minimal work in the controller, let templates pulladditional data as neededUse a bytecode cache with MapFileClassLoader
    • Asset ManagementGo see Kriss talk later today!
    • TestingSymfony2 rocks for unit and functional testing because Dependency Injection No base classes, no static dependencies, no ActiveRecord Client fakes "real" requests for functional testingFunctional Testing Pros: Tests configuration, Tests API not implementationUnit Testing Pros: Pinpoints issues, Very directed TestingRecommendation: Functional testing is recommended for controller actions Symfony2 provides WebTestCase and BrowserKit Unit testing for complex algorithms, third party APIs too hard to mockUse LiipFunctionalTesting to load fixtures, validate HTML5
    • DeploymentDebian style aka Liip Debian Packager Write a manifest in YAML Build Debian packages with MAKE Install with apt-get install Server specific settings are asked during install, change later with dpkg-reconfigure Maintain a global overview of all application dependencies in case of (security) updates
    • Third Party Bundles @weaverryan Ryan WeaverHeres a new years resolution: to *always*work on an existing Symfony2 bundle andnever recreate my own. #focus #teamwork27 Dec http://twitter.com/weaverryan/status/19565706752299009
    • Third Party BundlesMany vendors have already published bundles: FriendsOfSymfony (http://github.com/friendsofsymfony) UserBundle (forked from knplabs DoctrineUserBundle) FacebookBundle (forked from kriswallsmith) Liip (http://github.com/liip) FunctionalTestBundle MultiplexBundle ViewBundle Sonata (http://github.com/sonata-project) BaseApplicationBundleAdditionally, a few sites currently index community bundles: http://symfony2bundles.org/ http://symfohub.com/
    • Third Party BundlesBundles should follow the best practicesNo version-tagging or official package manager (yet)Use bundles by adding git submodules to your projectMaintain your own fork and "own" what you useNot all bundles are equally maintained Symfony2 API changes => broken bundles If you track fabpot/symfony, learn to migrate bundlesAvoid rewriting a bundles services/parameters directly The bundles DI extension should allow for such configuration; if not, submit a pull request If absolutely necessary, a CompilerPass is cleaner
    • Contributing to Third Party Bundles Similar to Symfony2s own patch guidlines Fork and add remote repository Merge regularly to keep up-to-date Avoid committing directly to your master Merges from upstream should be fast-forwards Once upstream changes are stable, bump your projects submodule pointer
    • Contributing to Third Party Bundles Create branches for patches and new features Cant wait to use this in your project? Temporarily change your project submodule to point to your branch until your pull request is accepted. Help ensure that your pull request merges cleanly Create feature branch based on upstreams master Rebase on upstreams master when finished
    • Contributing to Third Party Bundles Was your pull request accepted? Congratulations! Dont merge your feature branch into master! Doing so would cause your master to divert Merge upstreams master into your master Delete your feature branch Update your projects submodule to point to master
    • ResourcesIf you want to jump in and contribute:http://docs.symfony-reloaded.org/master/contributing/community/other.htmlIf you are still fuzzy on Dependency Injection:http://fabien.potencier.org/article/11/what-is-dependency-injectionIf you keep up with Fabiens Symfony2 repository:http://docs.symfony-reloaded.org/master/