High Performance Web Apps con PHP e Symfony 2

2,594 views
2,495 views

Published on

Slides del workshop tenuto da Giorgio Cefaro e Eugenio Pombi al Codemotion 2013

Published in: Technology
3 Comments
2 Likes
Statistics
Notes
No Downloads
Views
Total views
2,594
On SlideShare
0
From Embeds
0
Number of Embeds
286
Actions
Shares
0
Downloads
11
Comments
3
Likes
2
Embeds 0
No embeds

No notes for slide

High Performance Web Apps con PHP e Symfony 2

  1. 1. High Performance WebApps con PHPe Symfony 2di Giorgio Cefaro ed Eugenio Pombi
  2. 2. Giorgio Cefaro@giorrrgiogiorgiocefaro.com
  3. 3. Eugenio Pombi@euxpomnerd2business.net
  4. 4. Symfony 2First, Symfony2 is a reusable set of standalone,decoupled, and cohesive PHP components that solvecommon web development problems. Then, based onthese components, Symfony2 is also a full-stack webframework. Fabien Potencier
  5. 5. Request > Response
  6. 6. http://symfony.com/download
  7. 7. get the git repogit clone git@bitbucket.org:eux/pugx_book.gitgit tag -lgit checkout {nomeTag}git stash nerd2business.net
  8. 8. http://pugx-book.localhost/config.php
  9. 9. tag cap1git checkout cap1
  10. 10. parameters-dist.ymlparameters: database_driver: pdo_mysql database_host: 127.0.0.1 database_port: ~ database_name: pugx_book database_user: root database_password: ~ mailer_transport: smtp mailer_host: 127.0.0.1 mailer_user: ~ mailer_password: ~ locale: en secret: ThisTokenIsNotSoSecretChangeIt
  11. 11. composercurl -s https://getcomposer.org/installer | phpcomposer.jsoncomposer.lock./composer.phar update./composer.phar installminimum-stability
  12. 12. virtual host<VirtualHost *:80> ServerName pugx-book.localhost DocumentRoot "/PATH TO PROJECT/pugx_book/web" DirectoryIndex index.php <Directory "/PATH TO PROJECT/pugx_book/web"> AllowOverride All Require all granted </Directory></VirtualHost>PATH TO PUGX PROJECT
  13. 13. /etc/hosts127.0.0.1 pugx-book.localhost
  14. 14. struttura
  15. 15. bundle
  16. 16. tag cap2git checkout cap2
  17. 17. il nostro bundle php app/console generate:bundle --namespace=PUGX/BookBundle --format=ymlBundle namespace [PUGX/BookBundle]:Bundle name [PUGXBookBundle]:Target directory [/home/USERNAME/PATH/pugx_book/src]:Configuration format (yml, xml, php, or annotation) [yml]:Do you want to generate the whole directory structure [no]? yes
  18. 18. DefaultControllerTest.phpDefaultControllerTest.phpsrc/PUGX/BookBundle/Tests/Controller/ DefaultControllerTest.phpphpunit -c app/
  19. 19. front controller/web/app.php/web/app_dev.php/app/config/config.yml/app/config/config_dev.yml/app/config/config_prod.yml/app/config/config_test.yml
  20. 20. routing/app/config/routing.ymlpugx_book: resource: "@PUGXBookBundle/Resources/config/routing.yml" prefix: //src/PUGX/BookBundle/Resources/config/routing.ymlpugx_book_homepage: pattern: / defaults: { _controller: PUGXBookBundle:Default:index }
  21. 21. controllerIn genere costituito da una classe che raggruppa una seriedi azioni definite attraverso metodi pubblici.Il nostro primo controller:src/PUGX/BookBundle/Controller/DefaultController.php
  22. 22. twigreturn $this->render(PUGXBookBundle:Default:index.html.twig);PUGXBookBundle: <NomeVendor><NomeBundle>Default: <NomeController>index.html.twig: <NomeTemplate>//src/PUGX/BookBundle/Resources/views/Default/index.html.twigHello world!http://symfony.com/it/doc/2.1/book/templating.html
  23. 23. yay! live coding//src/PUGX/BookBundle/Tests/Controller/DefaultControllerTest.php$this->assertTrue($client->getResponse()->isSuccessful());$this->assertRegExp("/Welcome/i", $crawler->filter(h1)->text());$this->assertTrue($crawler->filter(p)->count() > 0);//nav bar$this->assertTrue($crawler->filter(.navbar)->count() > 0);$this->assertEquals(1, $crawler->filter(.navbar > li)->count());$this->assertRegExp("/home/i", $crawler->filter(.navbar > li:nth-child(1))->text());
  24. 24. PHPUnit assertsverifichiamo che la risposta sia valida$this->assertTrue($client->getResponse()->isSuccessful());ci assicuriamo che l’elemento h1 contenga la parola "Welcome":$this->assertRegExp("/Welcome/i", $crawler->filter(h1)->text());$crawler è unistanza del componente DomCrawler di Sf2, permette di manipolaredocumenti XML e HTML attraverso xpath e css selector:http://symfony.com/doc/2.1/components/dom_crawler.html
  25. 25. PHPUnit assertsci assicuriamo che ci sia almeno un elemento p nella pagina di risposta:$this->assertTrue($crawler->filter(p)->count() > 0);verifichiamo che ci sia un oggetto del DOM che abbia la classe css navbar:$this->assertTrue($crawler->filter(.navbar)->count() > 0);verifichiamo che la navbar contenga un solo elemento li:$this->assertEquals(1, $crawler->filter(.navbar > li)->count());infine verifichiamo che il primo elemento li di navbar contenga il testo home$this->assertRegExp("/home/i", $crawler->filter(.navbar > li:nth-child(1))->text());
  26. 26. DefaultControllerTest.phpDefaultControllerTest.phpsrc/PUGX/BookBundle/Tests/Controller/ DefaultControllerTest.phpphpunit -c app/
  27. 27. DefaultControllerTest.phpDefaultControllerTest.phpTEST ROSSIThere was 1 error:1) PUGXBookBundleTestsControllerDefaultControllerTest::testIndexInvalidArgumentException: The current node list is empty./home/eux/Documents/www/symfony2/pugx_book/vendor/symfony/symfony/src/Symfony/Component/DomCrawler/Crawler.php:468/home/eux/Documents/www/symfony2/pugx_book/src/PUGX/BookBundle/Tests/Controller/DefaultControllerTest.php:16FAILURES!Tests: 1, Assertions: 1, Failures: 1.
  28. 28. make it GREEN//src/PUGX/BookBundle/Resources/views/Default/index.html.twig<!DOCTYPE html><html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>PUGX Book</title> </head> <body> <div id="sidebar"> <ul class="navbar"> <li><a href="/">Home</a></li> </ul> </div> <div id="content"> <h1>Welcome on PUGX Book</h1> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus ultrices, nisi quis portafermentum, magna ligula suscipit metus, quis blandit leo urna non diam. Sed non dui dui, quis porttitormassa. Phasellus convallis porta leo, sed vehicula eros ultrices sit amet.</p> </div> </body></html>
  29. 29. DefaultControllerTest.phpDefaultControllerTest.phpsrc/PUGX/BookBundle/Tests/Controller/ DefaultControllerTest.phpphpunit -c app/
  30. 30. DefaultControllerTest.phpDefaultControllerTest.phpTEST VERDIPHPUnit 3.6.11 by Sebastian Bergmann.Configuration read from /home/giorgio/Progetti/codemotion/pugx_book/app/phpunit.xml.dist.Time: 11 seconds, Memory: 17.50MbOK (1 test, 6 assertions)
  31. 31. tag cap3git stashgit checkout cap3
  32. 32. DefaultControllerTest.phpun elenco di libriVogliamo aggiungere una pagina che contieneuna lista di libri, ognuno con informazionirelative allautore e alla data di pubblicazione.
  33. 33. DefaultControllerTest.phpIl testScriviamo innanzi tutto il test testBooks() insrc/PUGX/BookBundle/Tests/Controller/DefaultControllerTest.php
  34. 34. DefaultControllerTest.phplentità BookLa struttura dati che rappresenta il nostro libroè lentità Book, definita in:src/PUGX/BookBundle/Entity/Book.php
  35. 35. DefaultControllerTest.phpla nuova rottaAggiungiamo una nuova rotta che risponderàallurl /books
  36. 36. DefaultControllerTest.phpla nuova actionAggiungiamo un metodo booksAction alDefaultController in cui ci limiteremo a crearetre instanze di Book, passandole al twig
  37. 37. DefaultControllerTest.phpil nuovo templateCreiamo un nuovo twig insrc/PUGX/BookBundle/Resources/views/Default/books.html.twige stampiamo la lista di libri in una tabellaEreditarietà dei template
  38. 38. tag cap4git checkout cap4
  39. 39. Doctrine - ORM Object Relational Mapping class Book { public $title; public $author; public $publicationDate }
  40. 40. Doctrine DBAL Application Doctrine DBAL PDO PostgreSQL MySQL SQLite
  41. 41. Book entity/** * @ORMEntity * @ORMTable(name="book") */class Book{ [...] }src/PUGX/BookBundle/Entity/Book.phphttp://symfony.com/it/doc/2.1/book/doctrine.html#book-doctrine-field-types
  42. 42. parameters.yml/app/config/parameters.ymldatabase_driver: pdo_mysqldatabase_host: 127.0.0.1database_port: ~database_name: pugx_bookdatabase_user: rootdatabase_password: ~
  43. 43. Doctrine commandsphp app/console doctrine:database:createphp app/console doctrine:database:drop --forcephp app/console doctrine:schema:create
  44. 44. Doctrine migrationsdirectory:/app/DoctrineMigrationstable:migration_versionsphp app/console doctrine:migrations:diffphp app/console doctrine:migrations:migratephp app/console doctrine:migrations:execute --up NNNphp app/console doctrine:migrations:execute --down NNN
  45. 45. Doctrine fixturessrc/PUGX/BookBundle/DataFixtures/ORM/LoadBookData.phpphp app/console doctrine:fixtures:load
  46. 46. DefaultControllerTest.php/src/PUGX/BookBundle/Tests/Controller/DefaultControllerTest.phpControlliamo che i libri siano in ordine alfabetico
  47. 47. Query con doctrine/src/PUGX/BookBundle/Controller/DefaultController.phppublic function booksAction(){ $em = $this->getDoctrine()->getManager(); $books = $em->getRepository(PUGXBookBundle:Book)->findBy( array(), array(title => ASC) ); return $this->render(PUGXBookBundle:Default:books.html.twig, array(books => $books) );}
  48. 48. DefaultControllerTest.php/src/PUGX/BookBundle/Tests/Controller/DefaultControllerTest.phpAggiungiamo il test per una pagina di dettaglio (o 404)
  49. 49. rotta - action - template/src/PUGX/BookBundle/Resources/config/routing.yml/src/PUGX/BookBundle/Controller/DefaultController.php/src/PUGX/BookBundle/Resources/views/Default/bookDetail.html.twig
  50. 50. tag cap5git checkout cap5
  51. 51. doctrine - approfondimentiAuthor è un campo testualeUn autore è associato a più libriSpostiamo lautore in una entità separata.php app/console doctrine:generate:entity --entity="PUGXBookBundle:Author" --fields="name:string(255) surname:string(255) bio:text"
  52. 52. Author entity/** * @ORMEntity * @ORMTable(name="author") */class Author{ [...] }src/PUGX/BookBundle/Entity/Author.phphttp://symfony.com/it/doc/2.1/book/doctrine.html#book-doctrine-field-types
  53. 53. doctrine - associazioniPer definire lassociazione tra Book e Authorutilizziamo le annotazioni di DoctrineOneToMany(lato Author) e ManyToOne(latoBook)
  54. 54. doctrine - associazioniin src/PUGX/BookBundle/Entity/Author.php/*** @ORMOneToMany(targetEntity="PUGXBookBundleEntityBook",mappedBy="author")*/private $books;aggiungendo i metodi addBook, getBooks,setBooks e removeBook
  55. 55. doctrine - associazioniin src/PUGX/BookBundle/Entity/Book.php/*** @ORMManyToOne(targetEntity="PUGXBookBundleEntityAuthor",inversedBy="books")**/protected $author;aggiungendo i metodi setAuthor e getAuthor
  56. 56. doctrine - associazioniOsservazioneDoctrine nasconde la logica dellassociazione alivello database, in cui lassociazione è definitada un campo author_id della tabella book e unaforeign key.La parte inversa dellassociazione è ricostruitaautomaticamente da Doctrine.
  57. 57. doctrine - migrazionePer poter allineare il database ai cambiamenti, ènecessario generare e applicare una nuova migrazione:php app/console doctrine:migrations:diffphp app/console doctrine:migrations:migrate
  58. 58. doctrine - fixtures/src/PUGX/BookBundle/DataFixtures/ORM/LoadAuthorData.phpelemento$this->addReference(author-beck, $author);riferimento$this->getReference(author-beck)public function getOrder() { return 1;}
  59. 59. template/src/PUGX/BookBundle/Resources/views/Default/books.html.twig/src/PUGX/BookBundle/Resources/views/Default/bookDetail.html.twig{{ book.author.name }} {{ book.author.surname }}
  60. 60. problema!!!
  61. 61. causa
  62. 62. profiler$nbQuery = $client->getProfile()->getCollector(db)->getQueryCount();$this->assertEquals(1, $nbQuery);
  63. 63. custom repository/** * * @ORMEntity(repositoryClass="PUGXBookBundleRepositoryBookRepository") * @ORMTable(name="book") */class Book/src/PUGX/BookBundle/Repository/BookRepository.php/src/PUGX/BookBundle/Tests/Repository/BookRepositoryTest.php/src/PUGX/BookBundle/Controller/DefaultController.php$books = $em->getRepository(PUGXBookBundle:Book)->findAllWithAuthors();
  64. 64. DQLpublic function findAllWithAuthors(){ $query = $this->getEntityManager() ->createQuery( SELECT b, a FROM PUGXBookBundle:Book b INNER JOIN b.author a ORDER BY b.title ASC ); return $query->getResult();}
  65. 65. tag cap6git checkout cap6
  66. 66. DefaultControllerTestmetodotestCreate
  67. 67. form type/src/PUGX/BookBundle/Form/Type/BookType.php
  68. 68. routing problem/src/PUGX/BookBundle/Resources/config/routing.ymlpugx_book_detail: pattern: /books/{bookId} defaults: { _controller: PUGXBookBundle:Default:bookDetail }pugx_book_create: pattern: /books/create defaults: { _controller: PUGXBookBundle:Default:bookCreate }
  69. 69. solution/src/PUGX/BookBundle/Resources/config/routing.ymlpugx_book_detail: pattern: /books/{bookId} defaults: { _controller: PUGXBookBundle:Default:bookDetail } requirements: bookId: d+pugx_book_create: pattern: /books/create defaults: { _controller: PUGXBookBundle:Default:bookCreate }
  70. 70. form action/src/PUGX/BookBundle/Controller/DefaultController.phppublic function bookCreateAction(Request $request) { ...}
  71. 71. twig form/BookBundle/Resources/views/Default/bookCreate.html.twig
  72. 72. flash messages$this->get(session)->getFlashBag()->add(notice, Book successfully created);{% for flashMessage in app.session.flashbag.get(notice) %} <div class="notice"> {{ flashMessage }} </div>{% endfor %}
  73. 73. tearDownEliminazione del record inserito con il test
  74. 74. tag cap7git checkout cap7
  75. 75. security
  76. 76. tag extra1git checkout extra1

×