Commits

eugenio pombi committed d1150b5

introduces the author entity
improves the book list query

Comments (0)

Files changed (11)

app/DoctrineMigrations/Version20130312183147.php

+<?php
+
+namespace Application\Migrations;
+
+use Doctrine\DBAL\Migrations\AbstractMigration,
+    Doctrine\DBAL\Schema\Schema;
+
+/**
+ * Auto-generated Migration: Please modify to your need!
+ */
+class Version20130312183147 extends AbstractMigration
+{
+    public function up(Schema $schema)
+    {
+        // this up() migration is auto-generated, please modify it to your needs
+        $this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql", "Migration can only be executed safely on 'mysql'.");
+        
+        $this->addSql("CREATE TABLE author (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, surname VARCHAR(255) NOT NULL, bio LONGTEXT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB");
+        $this->addSql("ALTER TABLE book ADD author_id INT DEFAULT NULL, DROP author");
+        $this->addSql("ALTER TABLE book ADD CONSTRAINT FK_CBE5A331F675F31B FOREIGN KEY (author_id) REFERENCES author (id)");
+        $this->addSql("CREATE INDEX IDX_CBE5A331F675F31B ON book (author_id)");
+    }
+
+    public function down(Schema $schema)
+    {
+        // this down() migration is auto-generated, please modify it to your needs
+        $this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql", "Migration can only be executed safely on 'mysql'.");
+        
+        $this->addSql("ALTER TABLE book DROP FOREIGN KEY FK_CBE5A331F675F31B");
+        $this->addSql("DROP TABLE author");
+        $this->addSql("DROP INDEX IDX_CBE5A331F675F31B ON book");
+        $this->addSql("ALTER TABLE book ADD author VARCHAR(255) NOT NULL, DROP author_id");
+    }
+}

src/PUGX/BookBundle/Controller/DefaultController.php

     public function booksAction()
     {
         $em    = $this->getDoctrine()->getManager();
-        $books = $em->getRepository('PUGXBookBundle:Book')->findBy(array(), array('title' => 'ASC'));
+        $books = $em->getRepository('PUGXBookBundle:Book')->findAllWithAuthors();
 
         return $this->render('PUGXBookBundle:Default:books.html.twig', array('books' => $books));
     }

src/PUGX/BookBundle/DataFixtures/ORM/LoadAuthorData.php

+<?php
+
+namespace PUGX\BookBundle\DataFixtures\ORM;
+
+use Doctrine\Common\DataFixtures\AbstractFixture;
+use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
+use Doctrine\Common\Persistence\ObjectManager;
+use PUGX\BookBundle\Entity\Author;
+
+class LoadAuthorData extends AbstractFixture implements OrderedFixtureInterface
+{
+    public function load(ObjectManager $manager)
+    {
+        $author = new Author();
+        $author->setName("Kent");
+        $author->setSurname("Beck");
+        $author->setBio("Kent Beck is an American software engineer and the creator of the Extreme Programming and Test Driven Development software development methodologies, also named agile software development.");
+        $manager->persist($author);
+        $this->addReference('author-beck', $author);
+
+        $author = new Author();
+        $author->setName("Robert C.");
+        $author->setSurname("Martin");
+        $author->setBio("Robert Cecil Martin, known colloquially as 'Uncle Bob', is an American software consultant and author. Martin has been a software professional since 1970 and an international software consultant since 1990.");
+        $manager->persist($author);
+        $this->addReference('author-martin', $author);
+
+        $author = new Author();
+        $author->setName("Eric");
+        $author->setSurname("Evans");
+        $author->setBio("Eric Evans is a specialist in domain modeling and design in large business systems.");
+        $manager->persist($author);
+        $this->addReference('author-evans', $author);
+
+        $manager->flush();
+    }
+   
+    
+    public function getOrder()
+    {
+        return 1;
+    }
+}

src/PUGX/BookBundle/DataFixtures/ORM/LoadBookData.php

     public function load(ObjectManager $manager)
     {
         $books = array(
-            new Book("Extreme Programming Explained: Embrace Change", "Kent Beck", new \DateTime('1999-10-5')),
-            new Book("The Clean Coder", "Robert C. Martin", new \DateTime('2011-5-23')),
-            new Book("Domain-Driven Design: Tackling Complexity in the Heart of Software", "Eric Evans", new \DateTime('2003-8-30')),
+            new Book(
+                "Extreme Programming Explained: Embrace Change",
+                $this->getReference('author-beck'),
+                new \DateTime('1999-10-5')
+            ),
+            new Book(
+                "The Clean Coder",
+                $this->getReference('author-martin'),
+                new \DateTime('2011-5-23')
+            ),
+            new Book(
+                "Domain-Driven Design: Tackling Complexity in the Heart of Software",
+                $this->getReference('author-evans'),
+                new \DateTime('2003-8-30')
+            ),
         );
 
         foreach ($books as $book) {
 
         $manager->flush();
     }
-   
-    
+
     public function getOrder()
     {
-        return 1;
+        return 2;
     }
 }

src/PUGX/BookBundle/Entity/Author.php

+<?php
+
+namespace PUGX\BookBundle\Entity;
+
+use Doctrine\ORM\Mapping as ORM;
+use PUGX\BookBundle\Entity\Book;
+use Doctrine\Common\Collections\ArrayCollection;
+
+/**
+ * Author
+ *
+ * @ORM\Table(name="author")
+ * @ORM\Entity
+ */
+class Author
+{
+    /**
+     * @var integer
+     *
+     * @ORM\Column(name="id", type="integer")
+     * @ORM\Id
+     * @ORM\GeneratedValue(strategy="AUTO")
+     */
+    private $id;
+
+    /**
+     * @ORM\OneToMany(targetEntity="PUGX\BookBundle\Entity\Book", mappedBy="author")
+     */
+    private $books;
+
+    /**
+     * @var string
+     *
+     * @ORM\Column(name="name", type="string", length=255)
+     */
+    private $name;
+
+    /**
+     * @var string
+     *
+     * @ORM\Column(name="surname", type="string", length=255)
+     */
+    private $surname;
+
+    /**
+     * @var string
+     *
+     * @ORM\Column(name="bio", type="text")
+     */
+    private $bio;
+
+    public function __construct()
+    {
+        $this->books = new ArrayCollection();
+    }
+
+    /**
+     * Get id
+     *
+     * @return integer 
+     */
+    public function getId()
+    {
+        return $this->id;
+    }
+
+    /**
+     * Set name
+     *
+     * @param string $name
+     * @return Author
+     */
+    public function setName($name)
+    {
+        $this->name = $name;
+
+        return $this;
+    }
+
+    /**
+     * Get name
+     *
+     * @return string 
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * Set surname
+     *
+     * @param string $surname
+     * @return Author
+     */
+    public function setSurname($surname)
+    {
+        $this->surname = $surname;
+
+        return $this;
+    }
+
+    /**
+     * Get surname
+     *
+     * @return string 
+     */
+    public function getSurname()
+    {
+        return $this->surname;
+    }
+
+    /**
+     * Set bio
+     *
+     * @param string $bio
+     * @return Author
+     */
+    public function setBio($bio)
+    {
+        $this->bio = $bio;
+
+        return $this;
+    }
+
+    /**
+     * Get bio
+     *
+     * @return string 
+     */
+    public function getBio()
+    {
+        return $this->bio;
+    }
+
+    /**
+     * @param \Doctrine\Common\Collections\ArrayCollection $books
+     */
+    public function setBooks(ArrayCollection $books)
+    {
+        $this->books = $books;
+    }
+
+    /**
+     * @return \Doctrine\Common\Collections\ArrayCollection
+     */
+    public function getBooks()
+    {
+        return $this->books;
+    }
+
+    /**
+     * @param Book $book
+     */
+    public function addBook(Book $book)
+    {
+        $this->books->add($book);
+    }
+
+    /**
+     * @param Book $book
+     */
+    public function removeBook(Book $book)
+    {
+        $this->books->removeElement($book);
+    }
+}

src/PUGX/BookBundle/Entity/Book.php

 namespace PUGX\BookBundle\Entity;
 
 use Doctrine\ORM\Mapping as ORM;
+use PUGX\BookBundle\Entity\Author;
 
 /**
  *
- * @ORM\Entity
+ * @ORM\Entity(repositoryClass="PUGX\BookBundle\Repository\BookRepository")
  * @ORM\Table(name="book")
  */
 class Book
     protected $id;
 
     /**
-     * @ORM\Column(type="string", name="title", length=255)
-     */
-    protected $title;
+     * @ORM\ManyToOne(targetEntity="PUGX\BookBundle\Entity\Author", inversedBy="books")
+     **/
+    protected $author;
 
     /**
-     * @ORM\Column(type="string", name="author", length=255)
+     * @ORM\Column(type="string", name="title", length=255)
      */
-    protected $author;
+    protected $title;
 
     /**
      * @ORM\Column(type="date", name="publication_date")
     }
 
     /**
-     * @param string $author
+     * @param Author $author
      */
-    public function setAuthor($author)
+    public function setAuthor(Author $author)
     {
         $this->author = $author;
     }
 
     /**
-     * @return string
+     * @return Author
      */
     public function getAuthor()
     {
     {
         return $this->id;
     }
+
 }

src/PUGX/BookBundle/Repository/BookRepository.php

+<?php
+namespace PUGX\BookBundle\Repository;
+
+use Doctrine\ORM\EntityRepository;
+use Doctrine\ORM\Query;
+
+class BookRepository extends EntityRepository
+{
+    public function findAllWithAuthors()
+    {
+        $query = $this->createQueryBuilder('b')
+            ->select('b', 'a')
+            ->innerJoin('b.author', 'a')
+            ->orderBy('b.title',  'ASC')
+            ->getQuery()
+        ;
+
+        return $query->getResult();
+    }
+}

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

 {% extends '::base.html.twig' %}
 
 {% block content %}
-<article id="book-detail">
-    <h1>{{ book.title }}</h1> by {{ book.author }}
-    <p>
-        Published: {{ book.publicationDate|date("d/m/Y") }}
-    </p>
-</article>
+    <article id="book-detail">
+        <h1>{{ book.title }}</h1> by {{ book.author.name }} {{ book.author.surname }}
+        <p>
+            Published: {{ book.publicationDate|date("d/m/Y") }}
+        </p>
+    </article>
 {% endblock %}

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

             {% for book in books %}
                 <tr>
                     <td><a href="{{ path('pugx_book_detail', {'bookId':book.id}) }}">{{ book.title }}</a></td>
-                    <td>{{ book.author }}</td>
+                    <td>{{ book.author.name }} {{ book.author.surname }}</td>
                     <td>{{ book.publicationDate | date('d-m-Y') }}</td>
                 </tr>
             {% endfor %}

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

     public function testBooks()
     {
         $client = static::createClient();
+        $client->enableProfiler();
 
         $crawler = $client->request('GET', '/books');
         $this->assertTrue($client->getResponse()->isSuccessful());
         $this->assertRegExp("/Domain-Driven Design/i", $crawler->filter('.book-list > tbody > tr:nth-child(1) > td:nth-child(1)')->text());
         $this->assertRegExp("/Extreme Programming Explained/i", $crawler->filter('.book-list > tbody > tr:nth-child(2) > td:nth-child(1)')->text());
         $this->assertRegExp("/The Clean Coder/i", $crawler->filter('.book-list > tbody > tr:nth-child(3) > td:nth-child(1)')->text());
+
+        $nbQuery = $client->getProfile()->getCollector('db')->getQueryCount();
+        $this->assertEquals(1, $nbQuery);
     }
 
     public function testBookDetailOk()

src/PUGX/BookBundle/Tests/Repository/BookRepositoryTest.php

+<?php
+namespace PUGX\BookBundle\Tests\Repository;
+
+use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
+
+class BookRepositoryTest extends WebTestCase
+{
+    private $em;
+
+    private $repo;
+
+    public function setUp()
+    {
+        static::$kernel = static::createKernel();
+        static::$kernel->boot();
+        $this->em = static::$kernel->getContainer()
+            ->get('doctrine')
+            ->getManager()
+        ;
+
+        $this->repo = $this->em->getRepository('PUGXBookBundle:Book');
+    }
+
+    public function testFindAllWithAuthors()
+    {
+        $result = $this->repo->findAllWithAuthors();
+
+        $this->assertCount(3, $result);
+        $firstResult = $result[0];
+        $this->assertEquals("Domain-Driven Design: Tackling Complexity in the Heart of Software", $firstResult->getTitle());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function tearDown()
+    {
+        parent::tearDown();
+        $this->em->close();
+    }
+}