Your SlideShare is downloading. ×
0
UK Symfony Meetup             November, 2012                                           Symfony                            ...
Jakub Zalas a.k.a. Kuba○ Remembers symfony 1.0  (2007)○ Open Source contributor○ BDD advocate○ Works at Sensio Labs UK○ ZC...
Symfony War Stories● Bundling the code● Thinking outside of the bundle● Being lazy● Learning your stuff● Keeping your play...
Bundling                                           the codehttp://www.rgbstock.com/bigphoto/mfXkYUq
VS
Whenever in doubt...● Start simple and let the design emerge● Extract bundles when you need to reuse it  or you see it wou...
Thinking                                            outside of                                           the bundlehttp://...
VS
To keep your design clean...● Treat bundles as an integration layer  between PHP libraries and the Symfony  framework● In ...
Being lazyhttp://www.sxc.hu/photo/858871
Theres a bundle for that!
Learning                                  your stuffhttp://www.sxc.hu/photo/1095604
Have you ever used?● Event listeners and subscribers● Form data transformers● Twig extensions● Profiler extensions● DIC co...
Its easy!             lets see few examples...
Event listeners and subscribers (Doctrine) services:    sensio.listener.search_indexer:        class: SensioListenerSearch...
namespace SensioListener;use DoctrineORMEventLifecycleEventArgs;use SensioEntityProduct;class SearchIndexer{    public fun...
Lifecycle callbacks (Doctrine)/**  * @ORMEntity()  * @ORMHasLifecycleCallbacks()  */class User{     /**      * @ORMPrePers...
Event listeners and subscribers (Symfony)services:  sensio.action_listener:    class: SensioMyBundleEventListenerMyListene...
namespace SensioMyBundleEventListener;class MyListener{    public function onKernelController(                            ...
Event listeners and subscribers (Forms)$callback = function(FormEvent $event) {    if (null === $event->getData()) {      ...
Data transformers (Forms)class IssueToNumberTransformer                 implements DataTransformerInterface{    public fun...
$field = $builder->create(issue, text)    ->addModelTransformer(new IssueToNumberTransformer());$builder->add($field);
Twig extensions<!-- Instead of: --><div class="price">    ${{ 9800.333|number_format(2, ., ,) }}</div><!-- just do: --><di...
class SensioExtension extends Twig_Extension{    public function getFilters()    {        return array(            price =...
public function priceFilter(    $number, $decimals = 0, $decPoint = ., $sep = ,){    $price = number_format(        $numbe...
services:    sensio.twig.acme_extension:        class: SensioTwigSensioExtension        tags:            - { name: twig.ex...
Web profiler
Debugging commands./app/console container:debug./app/console container:debug twig.loader./app/console router:debug./app/co...
Debugging commands
http://www.rgbstock.com/bigphoto/mZTKnw6Keeping your playground clean
Use the service container!
public function publishAction($date){    $show = $this->findShow($date);    $fileName = sprintf(show-%s.json, $date->forma...
public function publishAction($date){    $show = $this->findShow($date);    $fileNameResolver = new FileNameResolver();   ...
Use the service container!public function publishAction($date){    $show = $this->findShow($date);    $publisher = $this->...
Be SOLID!
/**  * @ORMEntity()  */class Product{     // ...    public function createOrderReport($month)    {        // $this->em->ge...
class OrderReportGenerator{    private $em = null;    public function __construct(EntityManager $em)    {        $this->em...
Building quality inhttp://www.rgbstock.com/photo/nrcyovQ/perfect
Unit testsclass ReportTest extends PHPUnit_Framework_TestCase{    public function testThatItReturnsFilePath()    {        ...
... or specsnamespace spec;class Report extends PHPSpec2ObjectBehavior{    function it_returns_file_path()    {        $th...
Managing expectationsFeature: Viewing recent news on the homepage  As a Marketing Manager  I want Visitors to see recent n...
Thank you!
Upcoming SlideShare
Loading in...5
×

Symfony War Stories

4,016

Published on

UK Symfony Meetup, November 2012

Original presentation: https://docs.google.com/presentation/pub?id=1PLcqTby6yqSbfWlMIDHknH852DU6DO6OAgQJOtSEdsg&start=false&loop=false&delayms=3000

Published in: Technology

Transcript of "Symfony War Stories"

  1. 1. UK Symfony Meetup November, 2012 Symfony War Stories Jakub Zalas SensioLabsUKhttp://www.rgbstock.com/bigphoto/mhY2DCY
  2. 2. Jakub Zalas a.k.a. Kuba○ Remembers symfony 1.0 (2007)○ Open Source contributor○ BDD advocate○ Works at Sensio Labs UK○ ZCE & Sensio Labs ○ Twitter: @jakub_zalas Certified Symfony ○ Blog: http://zalas.eu Developer ○ Github: @jakzal
  3. 3. Symfony War Stories● Bundling the code● Thinking outside of the bundle● Being lazy● Learning your stuff● Keeping your playground clean● Building the quality in
  4. 4. Bundling the codehttp://www.rgbstock.com/bigphoto/mfXkYUq
  5. 5. VS
  6. 6. Whenever in doubt...● Start simple and let the design emerge● Extract bundles when you need to reuse it or you see it would improve clarity● Avoid two-way dependencies between bundles
  7. 7. Thinking outside of the bundlehttp://www.rgbstock.com/bigphoto/mfBYR2S
  8. 8. VS
  9. 9. To keep your design clean...● Treat bundles as an integration layer between PHP libraries and the Symfony framework● In your libraries, avoid dependencies on bundles
  10. 10. Being lazyhttp://www.sxc.hu/photo/858871
  11. 11. Theres a bundle for that!
  12. 12. Learning your stuffhttp://www.sxc.hu/photo/1095604
  13. 13. Have you ever used?● Event listeners and subscribers● Form data transformers● Twig extensions● Profiler extensions● DIC compiler passes● more...
  14. 14. Its easy! lets see few examples...
  15. 15. Event listeners and subscribers (Doctrine) services: sensio.listener.search_indexer: class: SensioListenerSearchIndexer tags: - name: doctrine.event_listener event: postPersist
  16. 16. namespace SensioListener;use DoctrineORMEventLifecycleEventArgs;use SensioEntityProduct;class SearchIndexer{ public function postPersist(LifecycleEventArgs $args) { $entity = $args->getEntity(); $entityManager = $args->getEntityManager(); if ($entity instanceof Product) { /* Index me */ } }}
  17. 17. Lifecycle callbacks (Doctrine)/** * @ORMEntity() * @ORMHasLifecycleCallbacks() */class User{ /** * @ORMPrePersist */ public function updateCreatedAt() { /* ... */ }}
  18. 18. Event listeners and subscribers (Symfony)services: sensio.action_listener: class: SensioMyBundleEventListenerMyListener tags: - name: kernel.event_listener event: kernel.controller method: onKernelController
  19. 19. namespace SensioMyBundleEventListener;class MyListener{ public function onKernelController( FilterControllerEvent $event) { $controller = $event->getController(); $request = $event->getRequest(); // ... }}
  20. 20. Event listeners and subscribers (Forms)$callback = function(FormEvent $event) { if (null === $event->getData()) { $formData = $event->getForm()->getData(); $event->setData($formData); }};$builder->add(email, text);$builder->get(email) ->addEventListener( FormEvents::PRE_BIND, $callback );
  21. 21. Data transformers (Forms)class IssueToNumberTransformer implements DataTransformerInterface{ public function transform($issue) { // return issue number } public function reverseTransform($number) { // return Issue instance }}
  22. 22. $field = $builder->create(issue, text) ->addModelTransformer(new IssueToNumberTransformer());$builder->add($field);
  23. 23. Twig extensions<!-- Instead of: --><div class="price"> ${{ 9800.333|number_format(2, ., ,) }}</div><!-- just do: --><div class="price"> {{ 9800.333|price }}</div>
  24. 24. class SensioExtension extends Twig_Extension{ public function getFilters() { return array( price => new Twig_Filter_Method( $this, priceFilter) ); } public function getName() { return sensio_extension; } public function priceFilter($number, /* ... */ ) {}}
  25. 25. public function priceFilter( $number, $decimals = 0, $decPoint = ., $sep = ,){ $price = number_format( $number, $decimals, $decPoint, $sep ); return $.$price;}
  26. 26. services: sensio.twig.acme_extension: class: SensioTwigSensioExtension tags: - { name: twig.extension }
  27. 27. Web profiler
  28. 28. Debugging commands./app/console container:debug./app/console container:debug twig.loader./app/console router:debug./app/console router:debug homepage./app/console router:match /logout
  29. 29. Debugging commands
  30. 30. http://www.rgbstock.com/bigphoto/mZTKnw6Keeping your playground clean
  31. 31. Use the service container!
  32. 32. public function publishAction($date){ $show = $this->findShow($date); $fileName = sprintf(show-%s.json, $date->format(Y-m-d)); while (file_exists($fileName)) { $fileName = $fileName.preg_replace(/.json$/, -1.json); } $options = array( /* options here */ ); $s3 = new AmazonS3($options); $objectOptions = array( body => json_encode($show), acl => $options[objectAcl]); if (!$s3->create_object(my-bucket, $fileName, $objectOptions) { throw new Exception(Could not save file); } // ...}
  33. 33. public function publishAction($date){ $show = $this->findShow($date); $fileNameResolver = new FileNameResolver(); $filesystem = $this->get(gafrette_filesystem); $publisher = new Publisher( $fileNameResolver, $filesystem ); $publisher->publish($show, $date);}
  34. 34. Use the service container!public function publishAction($date){ $show = $this->findShow($date); $publisher = $this->get(sensio.publisher); $publisher->publish($show, $date);}
  35. 35. Be SOLID!
  36. 36. /** * @ORMEntity() */class Product{ // ... public function createOrderReport($month) { // $this->em->getRepository() ... } public function setEntityManager($em) { $this->em = $em; }}
  37. 37. class OrderReportGenerator{ private $em = null; public function __construct(EntityManager $em) { $this->em = $em; } public function generate(Product $product, $month) { // ... }}
  38. 38. Building quality inhttp://www.rgbstock.com/photo/nrcyovQ/perfect
  39. 39. Unit testsclass ReportTest extends PHPUnit_Framework_TestCase{ public function testThatItReturnsFilePath() { $report = new Report(); $file = $report->create(January); $this->assertSame(/january.csv, $file); }}
  40. 40. ... or specsnamespace spec;class Report extends PHPSpec2ObjectBehavior{ function it_returns_file_path() { $this->create(January) ->shouldReturn(/january.csv); }}
  41. 41. Managing expectationsFeature: Viewing recent news on the homepage As a Marketing Manager I want Visitors to see recent news on the homepage In order to get them interested in the content Scenario: Viewing recent news Given there are 10 news items And there were 5 news items written since yesterday When I visit the homepage Then I should see 5 recent news items in the news section Scenario: There is not enough news Given there are 10 news items But there were 3 news items written since yesterday When I visit the homepage Then I should see 3 recent news items in the news section
  42. 42. Thank you!
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×