2017-07-29 74 views
0

想象我有兩個ORM實體:Symfony的 - 學說:設計REST API接收多對多實體

作者實體:

<?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, 
    ]; 
} 
} 

Book實體:

<?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, 
     ]; 
    } 
} 

由於此關係的結果生成了authors_books表。 我現在的目標是設計一個控制器,它會返回作者列表下面的json format例如:

{ 
    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控制器,像這樣的:

/** 
* @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' => ... 
     )); 
    } 
} 

至於現在我有一個兩個想法:

  1. 執行兩個請求:一個用於作者數組,另一個用於書籍數組。
  2. 將書實體數組的json表示作爲附加作者表的列保留。

但他們兩人似乎對我有點哈克。我該怎麼辦?

請注意,這是我試圖實現的簡化表示。儘管爲這個特定的例子使用多對多關係似乎是一個開銷,但對於我目前的任務來說,這是至關重要的。

+1

你能不能寫一個自定義的庫函數,抓住作者,與底層書的實體,然後配置序列化方法返回該數據? –

+0

查看JMS序列化程序。它可以根據您的配置序列化集合和所有相關的對象/集合。 jmsyst.com/bundles/JMSSerializerBundle – Vladislav

回答

1

怎麼樣你改變JsonSerialize在你的作者實體

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

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

    return $author; 
} 

,並在你的控制器:

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

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

如果你會重用這個邏輯很多,你可以考慮使用從symfony的串行組件,一個很大的指導可以在這裏找到https://thomas.jarrand.fr/blog/serialization/

也許使用JMSSerializer。

編輯

你DQL可能類似於以下內容:

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

我只是不明白這是如何工作的:我使用的是原生SQL查詢結果從'authors'表作者獲取。是否應該爲學說背後的每個相應的作者實體提取「書籍」? – Elias

+0

是的,或者如果您希望一次加載它,則可以爲此編寫自定義DQL,而不是原始查詢。檢查我的編輯 – RVandersteen

+0

感謝您的回覆,這正是我一直在尋找的! – Elias