2017-07-29 2 views
0

Stellen Ich habe eine zwei ORM Entities:Symfony - Lehre: Planung REST-API für viele zu viele Einheiten empfangen

Autor Entity:

<?php 

namespace AppBundle\Entity; 

use Doctrine\Common\Collections\ArrayCollection; 
use Doctrine\ORM\Mapping as ORM; 

/** 
* @ORM\Table(
*  name="authors", 
*  uniqueConstraints={@ORM\UniqueConstraint(name="date", columns={"author_id"})} 
*) 
*/ 
class Author implements \JsonSerializable 
{ 

/** 
* @var integer 
* 
* @ORM\Column(type="integer", nullable=false) 
* @ORM\Id 
* @ORM\GeneratedValue(strategy="IDENTITY") 
*/ 
public $id; 

/** 
* @var string 
* @ORM\Column(type="string", length=250, nullable=true) 
*/ 
public $name; 

/** 
* 
* Many Authors have Many Books. 
* @ORM\ManyToMany(targetEntity="Book") 
* @ORM\JoinTable(name="authors_books", 
*  joinColumns={@ORM\JoinColumn(name="author_id", referencedColumnName="id")}, 
*  inverseJoinColumns={@ORM\JoinColumn(name="book_id", referencedColumnName="id")} 
*  ) 
*/ 
public $books; 


public function __construct(User $user, \DateTime $startDate, \DateTime $ringDate, $phone, $name, $direction, $duration, $comment, $phoneId, $appVersion) 
{ 
    $this->name = $name; 
    $this->books = new \Doctrine\Common\Collections\ArrayCollection(); 

} 

public function jsonSerialize() 
{ 
    return [ 
     'id' => $this->id, 
     'name' => $this->name, 
     'books' => $this->books, 
    ]; 
} 
} 

Buch Entity:

<?php 

namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 

/** 
* @ORM\Table(name="books") 
* @ORM\Entity() 
*/ 
class Book implements \JsonSerializable 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(type="integer", nullable=false) 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="IDENTITY") 
    */ 
    public $id; 

    /** 
    * @var string 
    * @ORM\Column(type="string", length=120, nullable=false) 
    */ 
    public $description; 

    /** 
    * @var string 
    * @ORM\Column(type="string", length=10) 
    */ 
    public $color; 

    public function __construct($decription) 
    { 
     $this->$decription = $decription; 
    } 

    public function getId() 
    { 
     return $this->id; 
    } 

    public function getdecription() 
    { 
     return $this->decription; 
    } 

    public function setDecription($decription) 
    { 
     $this->decription = $decription; 
    } 

    function jsonSerialize() 
    { 
     return [ 
      'id' => $this->id, 
      'decription' => $this->decription, 
     ]; 
    } 
} 

Als Ergebnis dieser Beziehung wird eine Tabelle authors_books generiert. Mein Ziel für heute ist eine Steuerung zu entwickeln, die eine Liste der Autoren in der folgenden json format Beispiel zurückkehren würde:

{ 
    authors: [ 
     { 
      name: "Oscar Wilde", 
      books : [ 
       { 
        id: 1, 
        description: "The Picture of Dorian Gray" 
       }, 
       { 
        id: 2, 
        description: "The Happy Prince and Other Tales" 
       } 
      ] 
     }, 
     { 
      name: "Charles Dickens", 
      books : [ 
       { 
        id: 3, 
        description: "Great Expectations" 
       }, 
       { 
        id: 4, 
        description: "Oliver Twist" 
       } 
      ] 
     } 
     ] 
} 

Rest Controller wie folgt aus:

/** 
* @Route("/my/v1", service="app.authors_controller") 
*/ 
class MyController extends BaseApiController 
{ 

    /** 
    * @Route("/authors", name="my_v1_authors") 
    * @Method("GET") 
    */ 
    public function authors(Request $request) 
    { 

     $qb = $this->authorRepository->createQueryBuilder('c'); 

     return new JsonResponse(array(
      'authors' => ... 
     )); 
    } 
} 

Was ich jetzt eine haben zwei Ideen, um das zu erreichen:

  1. Ausführen von zwei Anfrage: eine für eine Reihe von Autoren und die andere für eine Reihe von Büchern.
  2. Die JSON-Repräsentation eines Arrays von Buch-Entities als zusätzliche Spalte der Authors-Tabelle beibehalten.

Aber beide scheinen mir ein bisschen hacky. Was soll ich machen?

Bitte beachten Sie, dass dies die vereinfachte Darstellung dessen ist, was ich erreichen möchte. Obwohl die Verwendung von Viele-zu-Viele-Beziehungen für dieses spezielle Beispiel ein Overhead zu sein scheint, ist dies für meine aktuelle Aufgabe entscheidend.

+1

Könnten Sie nicht eine benutzerdefinierten Repository-Funktion schreiben, die die Autoren packen, und die zugrunde liegende Buch Einheiten und eine dann konfigurieren Serialisierungsmethode, um diese Daten zurückzugeben? –

+0

Überprüfen Sie den JMS-Serializer. Es kann die Sammlung und alle verwandten Objekte/Sammlungen entsprechend Ihrer Konfiguration serialisieren. jmsyst.com/bundles/JMSSerializerBundle – Vladislav

Antwort

1

Wie über Sie Ihre JsonSerialize in Ihrem Autor Entität ändern

public function jsonSerialize() 
{ 
    $author = [ 
     'id' => $this->id, 
     'name' => $this->name, 
     'books' => [] 
    ]; 

    foreach($this->books as $book) 
    { 
     $author['books'][] = $book->jsonSerialize(); 
    } 

    return $author; 
} 

und in Ihrem Controller:

$authors = /** your optimized query here **/ 
$serializedAuthors = []; 

foreach($authors as $author) 
{ 
    $serializedAuthors[] = $author->jsonSerialize(); 
} 

Wenn Sie diese Logik eine Menge wiederverwenden könnte, könnten Sie mit der Serializer-Komponente von symfony betrachten , eine gute Anleitung finden Sie hier https://thomas.jarrand.fr/blog/serialization/

Oder vielleicht JMSSerializer verwenden.

EDIT

Ihre DQL etwas aussehen könnte wie folgt aus:

$authors = $this->getEntityManager()->createQuery(' 
    SELECT author, books 
    FROM AppBundle\Entity\Author author 
    JOIN author.books books 
')->getResult(); 
+0

Ich sehe nur nicht, wie dies funktionieren könnte: Ich hole mit nativen SQL-Abfrage-Ergebnisse für Autoren aus 'Autoren' Tabelle. Wird angenommen, dass diese Doktrin "Bücher" für jede entsprechende "Autor" -Einheit hinter Szenen holt? – Elias

+0

Ja, oder wenn Sie es lieber auf einmal laden möchten, könnten Sie anstelle einer unbearbeiteten Abfrage eine benutzerdefinierte DQL dafür schreiben. Überprüfen Sie meine Änderungen – RVandersteen

+0

Danke für Ihre Antwort, das ist genau das, was ich gesucht habe! – Elias

Verwandte Themen