2017-07-29 77 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