high performance web apps con php e symfony 2

76
High Performance Web Apps con PHP e Symfony 2 di Giorgio Cefaro ed Eugenio Pombi

Upload: giorgio-cefaro

Post on 18-May-2015

2.204 views

Category:

Technology


0 download

DESCRIPTION

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

TRANSCRIPT

Page 1: High Performance Web Apps con PHP  e Symfony 2

High Performance Web Apps con PHP e Symfony 2

di Giorgio Cefaro ed Eugenio Pombi

Page 2: High Performance Web Apps con PHP  e Symfony 2

Giorgio Cefaro

@giorrrgiogiorgiocefaro.com

Page 3: High Performance Web Apps con PHP  e Symfony 2

Eugenio Pombi

@euxpomnerd2business.net

Page 4: High Performance Web Apps con PHP  e Symfony 2

Symfony 2

First, Symfony2 is a reusable set of standalone, decoupled, and cohesive PHP components that solve common web development problems. Then, based on these components, Symfony2 is also a full-stack web framework. Fabien Potencier

Page 5: High Performance Web Apps con PHP  e Symfony 2

Request > Response

Page 6: High Performance Web Apps con PHP  e Symfony 2

http://symfony.com/download

Page 7: High Performance Web Apps con PHP  e Symfony 2

get the git repogit clone [email protected]:eux/pugx_book.git

git tag -l

git checkout {nomeTag}

git stash

nerd2business.net

Page 8: High Performance Web Apps con PHP  e Symfony 2

http://pugx-book.localhost/config.php

Page 9: High Performance Web Apps con PHP  e Symfony 2

tag cap1

git checkout cap1

Page 10: High Performance Web Apps con PHP  e Symfony 2

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

Page 11: High Performance Web Apps con PHP  e Symfony 2

composercurl -s https://getcomposer.org/installer | php

composer.jsoncomposer.lock

./composer.phar update

./composer.phar install

minimum-stability

Page 12: High Performance Web Apps con PHP  e Symfony 2

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

Page 13: High Performance Web Apps con PHP  e Symfony 2

/etc/hosts

127.0.0.1 pugx-book.localhost

Page 14: High Performance Web Apps con PHP  e Symfony 2

struttura

Page 15: High Performance Web Apps con PHP  e Symfony 2

bundle

Page 16: High Performance Web Apps con PHP  e Symfony 2

tag cap2

git checkout cap2

Page 17: High Performance Web Apps con PHP  e Symfony 2

il nostro bundlephp app/console generate:bundle --namespace=PUGX/BookBundle

--format=yml

Bundle 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

Page 18: High Performance Web Apps con PHP  e Symfony 2

DefaultControllerTest.php

DefaultControllerTest.php

src/PUGX/BookBundle/Tests/Controller/DefaultControllerTest.php

phpunit -c app/

Page 19: High Performance Web Apps con PHP  e Symfony 2

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

Page 20: High Performance Web Apps con PHP  e Symfony 2

routing/app/config/routing.yml

pugx_book:

resource: "@PUGXBookBundle/Resources/config/routing.yml"

prefix: /

/src/PUGX/BookBundle/Resources/config/routing.yml

pugx_book_homepage:

pattern: /

defaults: { _controller: PUGXBookBundle:Default:index }

Page 21: High Performance Web Apps con PHP  e Symfony 2

controller

In genere costituito da una classe che raggruppa una serie di azioni definite attraverso metodi pubblici.

Il nostro primo controller:src/PUGX/BookBundle/Controller/DefaultController.php

Page 22: High Performance Web Apps con PHP  e Symfony 2

twig

return $this->render('PUGXBookBundle:Default:index.html.twig');

PUGXBookBundle: <NomeVendor><NomeBundle>

Default: <NomeController>

index.html.twig: <NomeTemplate>

//src/PUGX/BookBundle/Resources/views/Default/index.html.twig

Hello world!

http://symfony.com/it/doc/2.1/book/templating.html

Page 23: High Performance Web Apps con PHP  e Symfony 2

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());

Page 24: High Performance Web Apps con PHP  e Symfony 2

PHPUnit asserts

verifichiamo 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 è un'istanza del componente DomCrawler di Sf2, permette di manipolare documenti XML e HTML attraverso xpath e css selector:http://symfony.com/doc/2.1/components/dom_crawler.html

Page 25: High Performance Web Apps con PHP  e Symfony 2

PHPUnit asserts

ci 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());

Page 26: High Performance Web Apps con PHP  e Symfony 2

DefaultControllerTest.php

DefaultControllerTest.php

src/PUGX/BookBundle/Tests/Controller/DefaultControllerTest.php

phpunit -c app/

Page 27: High Performance Web Apps con PHP  e Symfony 2

DefaultControllerTest.php

DefaultControllerTest.php

TEST ROSSI

There was 1 error:

1) PUGX\BookBundle\Tests\Controller\DefaultControllerTest::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:16

FAILURES!Tests: 1, Assertions: 1, Failures: 1.

Page 28: High Performance Web Apps con PHP  e Symfony 2

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 porta fermentum, magna ligula suscipit metus, quis blandit leo urna non diam. Sed non dui dui, quis porttitor massa. Phasellus convallis porta leo, sed vehicula eros ultrices sit amet.</p>

</div>

</body></html>

Page 29: High Performance Web Apps con PHP  e Symfony 2

DefaultControllerTest.php

DefaultControllerTest.php

src/PUGX/BookBundle/Tests/Controller/DefaultControllerTest.php

phpunit -c app/

Page 30: High Performance Web Apps con PHP  e Symfony 2

DefaultControllerTest.php

DefaultControllerTest.php

TEST VERDI

PHPUnit 3.6.11 by Sebastian Bergmann.

Configuration read from /home/giorgio/Progetti/codemotion/pugx_book/app/phpunit.xml.dist

.

Time: 11 seconds, Memory: 17.50Mb

OK (1 test, 6 assertions)

Page 31: High Performance Web Apps con PHP  e Symfony 2

tag cap3

git stash

git checkout cap3

Page 32: High Performance Web Apps con PHP  e Symfony 2

DefaultControllerTest.php

un elenco di libri

Vogliamo aggiungere una pagina che contiene una lista di libri, ognuno con informazioni relative all'autore e alla data di pubblicazione.

Page 33: High Performance Web Apps con PHP  e Symfony 2

DefaultControllerTest.php

Il test

Scriviamo innanzi tutto il test testBooks() insrc/PUGX/BookBundle/Tests/Controller/DefaultControllerTest.php

Page 34: High Performance Web Apps con PHP  e Symfony 2

DefaultControllerTest.php

l'entità Book

La struttura dati che rappresenta il nostro libro è l'entità Book, definita in:src/PUGX/BookBundle/Entity/Book.php

Page 35: High Performance Web Apps con PHP  e Symfony 2

DefaultControllerTest.php

la nuova rotta

Aggiungiamo una nuova rotta che risponderà all'url /books

Page 36: High Performance Web Apps con PHP  e Symfony 2

DefaultControllerTest.php

la nuova action

Aggiungiamo un metodo booksAction al DefaultController in cui ci limiteremo a creare tre instanze di Book, passandole al twig

Page 37: High Performance Web Apps con PHP  e Symfony 2

DefaultControllerTest.php

il nuovo template

Creiamo un nuovo twig in src/PUGX/BookBundle/Resources/views/Default/books.html.twig

e stampiamo la lista di libri in una tabella

Ereditarietà dei template

Page 38: High Performance Web Apps con PHP  e Symfony 2

tag cap4

git checkout cap4

Page 39: High Performance Web Apps con PHP  e Symfony 2

Doctrine - ORMObject Relational Mapping

class Book { public $title; public $author; public $publicationDate}

Page 40: High Performance Web Apps con PHP  e Symfony 2

Doctrine DBAL

PostgreSQL MySQL SQLite

PDO

Doctrine DBAL

Application

Page 41: High Performance Web Apps con PHP  e Symfony 2

Book entity/** * @ORM\Entity * @ORM\Table(name="book") */class Book{ [...] }

src/PUGX/BookBundle/Entity/Book.php

http://symfony.com/it/doc/2.1/book/doctrine.html#book-doctrine-field-types

Page 42: High Performance Web Apps con PHP  e Symfony 2

parameters.yml/app/config/parameters.yml

database_driver: pdo_mysqldatabase_host: 127.0.0.1database_port: ~database_name: pugx_bookdatabase_user: rootdatabase_password: ~

Page 43: High Performance Web Apps con PHP  e Symfony 2

Doctrine commandsphp app/console doctrine:database:create

php app/console doctrine:database:drop --force

php app/console doctrine:schema:create

Page 44: High Performance Web Apps con PHP  e Symfony 2

Doctrine migrationsdirectory:/app/DoctrineMigrations

table:migration_versions

php app/console doctrine:migrations:diffphp app/console doctrine:migrations:migratephp app/console doctrine:migrations:execute --up NNNphp app/console doctrine:migrations:execute --down NNN

Page 45: High Performance Web Apps con PHP  e Symfony 2

Doctrine fixturessrc/PUGX/BookBundle/DataFixtures/ORM/LoadBookData.php

php app/console doctrine:fixtures:load

Page 46: High Performance Web Apps con PHP  e Symfony 2

DefaultControllerTest.php/src/PUGX/BookBundle/Tests/Controller/DefaultControllerTest.php

Controlliamo che i libri siano in ordine alfabetico

Page 47: High Performance Web Apps con PHP  e Symfony 2

Query con doctrine/src/PUGX/BookBundle/Controller/DefaultController.php

public 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) );}

Page 48: High Performance Web Apps con PHP  e Symfony 2

DefaultControllerTest.php/src/PUGX/BookBundle/Tests/Controller/DefaultControllerTest.php

Aggiungiamo il test per una pagina di dettaglio (o 404)

Page 49: High Performance Web Apps con PHP  e Symfony 2

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

Page 50: High Performance Web Apps con PHP  e Symfony 2

tag cap5

git checkout cap5

Page 51: High Performance Web Apps con PHP  e Symfony 2

doctrine - approfondimentiAuthor è un campo testualeUn autore è associato a più libriSpostiamo l'autore in una entità separata.

php app/console doctrine:generate:entity --entity="PUGXBookBundle:Author" --fields="name:string(255) surname:string(255) bio:text"

Page 52: High Performance Web Apps con PHP  e Symfony 2

Author entity/** * @ORM\Entity * @ORM\Table(name="author") */class Author{ [...] }

src/PUGX/BookBundle/Entity/Author.php

http://symfony.com/it/doc/2.1/book/doctrine.html#book-doctrine-field-types

Page 53: High Performance Web Apps con PHP  e Symfony 2

doctrine - associazioni

Per definire l'associazione tra Book e Author utilizziamo le annotazioni di Doctrine OneToMany(lato Author) e ManyToOne(lato Book)

Page 54: High Performance Web Apps con PHP  e Symfony 2

doctrine - associazioniin src/PUGX/BookBundle/Entity/Author.php

/**

* @ORM\OneToMany(targetEntity="PUGX\BookBundle\Entity\Book", mappedBy="author")

*/

private $books;

aggiungendo i metodi addBook, getBooks, setBooks e removeBook

Page 55: High Performance Web Apps con PHP  e Symfony 2

doctrine - associazioniin src/PUGX/BookBundle/Entity/Book.php

/**

* @ORM\ManyToOne(targetEntity="PUGX\BookBundle\Entity\Author", inversedBy="books")

**/

protected $author;

aggiungendo i metodi setAuthor e getAuthor

Page 56: High Performance Web Apps con PHP  e Symfony 2

doctrine - associazioniOsservazione

Doctrine nasconde la logica dell'associazione a livello database, in cui l'associazione è definita da un campo author_id della tabella book e una foreign key. La parte inversa dell'associazione è ricostruita automaticamente da Doctrine.

Page 57: High Performance Web Apps con PHP  e Symfony 2

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

Page 58: High Performance Web Apps con PHP  e Symfony 2

doctrine - fixtures/src/PUGX/BookBundle/DataFixtures/ORM/LoadAuthorData.php

elemento$this->addReference('author-beck', $author);

riferimento$this->getReference('author-beck')

public function getOrder() { return 1;}

Page 59: High Performance Web Apps con PHP  e Symfony 2

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 }}

Page 60: High Performance Web Apps con PHP  e Symfony 2

problema!!!

Page 61: High Performance Web Apps con PHP  e Symfony 2

causa

Page 62: High Performance Web Apps con PHP  e Symfony 2

profiler$nbQuery = $client->getProfile()->getCollector('db')->getQueryCount();

$this->assertEquals(1, $nbQuery);

Page 63: High Performance Web Apps con PHP  e Symfony 2

custom repository/** * * @ORM\Entity(repositoryClass="PUGX\BookBundle\Repository\BookRepository") * @ORM\Table(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();

Page 64: High Performance Web Apps con PHP  e Symfony 2

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();}

Page 65: High Performance Web Apps con PHP  e Symfony 2

tag cap6

git checkout cap6

Page 66: High Performance Web Apps con PHP  e Symfony 2

DefaultControllerTest

metodo

testCreate

Page 67: High Performance Web Apps con PHP  e Symfony 2

form type

/src/PUGX/BookBundle/Form/Type/BookType.php

Page 68: High Performance Web Apps con PHP  e Symfony 2

routing problem/src/PUGX/BookBundle/Resources/config/routing.yml

pugx_book_detail: pattern: /books/{bookId} defaults: { _controller: PUGXBookBundle:Default:bookDetail }

pugx_book_create: pattern: /books/create defaults: { _controller: PUGXBookBundle:Default:bookCreate }

Page 69: High Performance Web Apps con PHP  e Symfony 2

solution/src/PUGX/BookBundle/Resources/config/routing.yml

pugx_book_detail: pattern: /books/{bookId} defaults: { _controller: PUGXBookBundle:Default:bookDetail } requirements: bookId: \d+

pugx_book_create: pattern: /books/create defaults: { _controller: PUGXBookBundle:Default:bookCreate }

Page 70: High Performance Web Apps con PHP  e Symfony 2

form action/src/PUGX/BookBundle/Controller/DefaultController.php

public function bookCreateAction(Request $request) { ...}

Page 71: High Performance Web Apps con PHP  e Symfony 2

twig form

/BookBundle/Resources/views/Default/bookCreate.html.twig

Page 72: High Performance Web Apps con PHP  e Symfony 2

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 %}

Page 73: High Performance Web Apps con PHP  e Symfony 2

tearDown

Eliminazione del record inserito con il test

Page 74: High Performance Web Apps con PHP  e Symfony 2

tag cap7

git checkout cap7

Page 75: High Performance Web Apps con PHP  e Symfony 2

security

Page 76: High Performance Web Apps con PHP  e Symfony 2

tag extra1

git checkout extra1