4. 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
17. il nostro bundle
php 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
21. 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
24. 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
25. 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());
27. DefaultControllerTest.php
DefaultControllerTest.php
TEST ROSSI
There was 1 error:
1) PUGXBookBundleTestsControllerDefaultControllerTest::testIndex
InvalidArgumentException: The current node list is empty.
/home/eux/Documents/www/symfony2/pugx_book/vendor/symfony/symfony/src/Symfony/Component/DomCrawler/Cra
wler.php:468
/home/eux/Documents/www/symfony2/pugx_book/src/PUGX/BookBundle/Tests/Controller/DefaultControllerTest.php:
16
FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
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 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>
32. 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.
51. doctrine - approfondimenti
Author è un campo testuale
Un autore è associato a più libri
Spostiamo l'autore in una entità separata.
php app/console doctrine:generate:entity --
entity="PUGXBookBundle:Author" --fields="name:
string(255) surname:string(255) bio:text"
53. doctrine - associazioni
Per definire l'associazione tra Book e Author
utilizziamo le annotazioni di Doctrine
OneToMany(lato Author) e ManyToOne(lato
Book)
54. doctrine - associazioni
in src/PUGX/BookBundle/Entity/Author.php
/**
* @ORMOneToMany(targetEntity="PUGXBookBundleEntityBook",
mappedBy="author")
*/
private $books;
aggiungendo i metodi addBook, getBooks,
setBooks e removeBook
55. doctrine - associazioni
in src/PUGX/BookBundle/Entity/Book.php
/**
* @ORMManyToOne(targetEntity="PUGXBookBundleEntityAuthor",
inversedBy="books")
**/
protected $author;
aggiungendo i metodi setAuthor e getAuthor
56. doctrine - associazioni
Osservazione
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.
57. doctrine - migrazione
Per poter allineare il database ai cambiamenti, è
necessario generare e applicare una nuova migrazione:
php app/console doctrine:migrations:diff
php app/console doctrine:migrations:migrate
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. DQL
public 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();
}