Doctrine 2.1 i INDEX BY

Wraz z udostepnieniem Doctrine w wersji 2.1 pojawiło się kilka zmian. Jedną z nich jest możliwość zmiany klucza dla tablic elementów pobieranych z bazy danych.

Do tej pory pobranie kilku rekordów z bazy danych skutkowało utworzeniem tablicy indeksowanej, gdzie kluczem były liczby 0,1,2,3,… a wartościami encje lub tablice rekordów. Dzięki nowej opcji zaimplementowanej w Doctrine w wersji 2.1 można tą sytuacje zmienić i zamiast takiego klucza można użyć innej wartości pod warunkiem, że jest to pole unikalne

Opcji INDEX BY możemy użyć przy dowolnej relacji OneToMany lub ManyToMany, dodaj klauzulę indexBy.

/**
* @ORM\OneToMany(targetEntity="Book", mappedBy="author", indexBy="id")
*/
protected $books;

Można także tworząc zapytanie poprzez QueryBuilder skorzystać z dodatkowego paramtru methody from i oznaczyć np. pole id jako te które ma stanowić klucz dla pobranej kolekcji danych.

$this->getEntityManager()->createQueryBuilder()
->form($this->getClassName(), 'b', 'b.id')
->select('b'); 

Przyjrzyjmy się poniższemu przykładowi. Mamy tu dwie encje: Book – książki i Author – autorzy. Jak łatwo zauważyć istnieje między tymi encjami relacja jeden do wielu.

<?php

namespace Examples\IndexByBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Book
 *
 * @ORM\Table(name="indexby_books")
 * @ORM\Entity
 */
class Book
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var integer
     *
     * @ORM\Column(name="author_id", type="integer")
     */
    private $author_id;

    /**
     * @var string
     *
     * @ORM\Column(name="title", type="string", length=255)
     */
    private $title;

    /**
     * @var string
     *
     * @ORM\Column(name="description", type="text")
     */
    private $description;

    /**
     * @ORM\ManyToOne(targetEntity="Author", inversedBy="books")
     * @ORM\JoinColumn(name="author_id", referencedColumnName="id")
     */
    protected $author;


    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set title
     *
     * @param string $title
     * @return Book
     */
    public function setTitle($title)
    {
        $this->title = $title;
    
        return $this;
    }

    /**
     * Get title
     *
     * @return string 
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * Set author_id
     *
     * @param integer $authorId
     * @return Book
     */
    public function setAuthorId($authorId)
    {
        $this->author_id = $authorId;
    
        return $this;
    }

    /**
     * Get author_id
     *
     * @return integer 
     */
    public function getAuthorId()
    {
        return $this->author_id;
    }

    /**
     * Set description
     *
     * @param string $description
     * @return Book
     */
    public function setDescription($description)
    {
        $this->description = $description;
    
        return $this;
    }

    /**
     * Get description
     *
     * @return string 
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * Set author
     *
     * @param \Examples\IndexByBundle\Entity\Author $author
     * @return Book
     */
    public function setAuthor(\Examples\IndexByBundle\Entity\Author $author = null)
    {
        $this->author = $author;
    
        return $this;
    }

    /**
     * Get author
     *
     * @return \Examples\IndexByBundle\Entity\Author 
     */
    public function getAuthor()
    {
        return $this->author;
    }
}
<?php

namespace Examples\IndexByBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Author
 *
 * @ORM\Table(name="indexby_authors")
 * @ORM\Entity
 */
class Author
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=100)
     */
    private $name;

    /**
     * @var string
     *
     * @ORM\Column(name="surname", type="string", length=100)
     */
    private $surname;

    /**
     * @ORM\OneToMany(targetEntity="Book", mappedBy="author", indexBy="id")
     */
    protected $books;


    /**
     * 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;
    }
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->books = new \Doctrine\Common\Collections\ArrayCollection();
    }
    
    /**
     * Add books
     *
     * @param \Examples\IndexByBundle\Entity\Book $books
     * @return Author
     */
    public function addBook(\Examples\IndexByBundle\Entity\Book $books)
    {
        $this->books[] = $books;
    
        return $this;
    }

    /**
     * Remove books
     *
     * @param \Examples\IndexByBundle\Entity\Book $books
     */
    public function removeBook(\Examples\IndexByBundle\Entity\Book $books)
    {
        $this->books->removeElement($books);
    }

    /**
     * Get books
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getBooks()
    {
        return $this->books;
    }
}

 Jeśli teraz pobierzemy z bazy danych zestaw autorów i ich książek to możemy uzyskać np. taki zestaw danych na którym widać, że dla każdego autora mamy tablicę książek, której kluczami są identyfikatory książek. Nie ma tu znaczenia czy pobieramy dane metodą getArrayResult() czy getResult().

array
  0 => 
    array
      'id' => int 3
      'name' => string 'John Ronald Reuel' (length=17)
      'surname' => string 'Tolkien' (length=7)
      'books' => 
        array
          8 => 
            array
              'id' => int 8
              'author_id' => int 3
              'title' => string 'Hobbit, czyli tam i z powrotem' (length=30)
              'description' => string 'Opowiada o wyprawie podjętej przez kompanię Thorina do okupowanej przez smoka Smauga Samotnej Góry w celu zabicia go i odzyskania dawnej siedziby krasnoludów. Po drodze, w jaskini Golluma, Bilbo Baggins znajduje Jedyny Pierścień.' (length=235)
          9 => 
            array
              'id' => int 9
              'author_id' => int 3
              'title' => string 'Władca Pierścieni' (length=19)
              'description' => string 'Powieść fantasy, której akcja rozgrywa się w mitycznym świecie Śródziemia.' (length=81)
          10 => 
            array
              'id' => int 10
              'author_id' => int 3
              'title' => string 'Historia Śródziemia' (length=21)
              'description' => string 'Cykl książek pokazuje krok po kroku etapy tworzenia tego fikcyjnego świata, od pierwszych tekstów z 1916 roku, aż po ostatnie teksty z lat 70. XX wieku' (length=156)
  1 => &
    array
      'id' => int 4
      'name' => string 'Andrzej' (length=7)
      'surname' => string 'Sapkowski' (length=9)
      'books' => 
        array
          11 => 
            array
              'id' => int 11
              'author_id' => int 4
              'title' => string 'Wiedźmin' (length=9)
              'description' => string '' (length=0)
          12 => &
            array
              'id' => int 12
              'author_id' => int 4
              'title' => string 'Ostatnie życzenie' (length=18)
              'description' => string '' (length=0)
Doctrine 2.1 i INDEX BY
Przewiń do góry