Symfony - Doctrine : 设计用于接收多对多实体的 REST API



想象一下我有两个ORM实体:

作者实体:

<?php
namespace AppBundleEntity;
use DoctrineCommonCollectionsArrayCollection;
use DoctrineORMMapping as ORM;
/**
* @ORMTable(
*        name="authors",
*        uniqueConstraints={@ORMUniqueConstraint(name="date", columns={"author_id"})}
* )
*/
class Author implements JsonSerializable
{
/**
* @var integer
*
* @ORMColumn(type="integer", nullable=false)
* @ORMId
* @ORMGeneratedValue(strategy="IDENTITY")
*/
public $id;
/**
* @var string
* @ORMColumn(type="string", length=250, nullable=true)
*/
public $name;
/**
*
* Many Authors have Many Books.
* @ORMManyToMany(targetEntity="Book")
* @ORMJoinTable(name="authors_books",
*      joinColumns={@ORMJoinColumn(name="author_id", referencedColumnName="id")},
*      inverseJoinColumns={@ORMJoinColumn(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 DoctrineCommonCollectionsArrayCollection();
}
public function jsonSerialize()
{
return [
'id' => $this->id,
'name' => $this->name,
'books' => $this->books,
];
}
}

图书实体:

<?php
namespace AppBundleEntity;
use DoctrineORMMapping as ORM;
/**
* @ORMTable(name="books")
* @ORMEntity()
*/
class Book implements JsonSerializable
{
/**
* @var integer
*
* @ORMColumn(type="integer", nullable=false)
* @ORMId
* @ORMGeneratedValue(strategy="IDENTITY")
*/
public $id;
/**
* @var string
* @ORMColumn(type="string", length=120, nullable=false)
*/
public $description;
/**
* @var string
* @ORMColumn(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 表示形式保留为其他作者表的列。

但在我看来,他们两个都有点笨拙。我该怎么办?

请注意,这是我试图实现的目标的简化表示。尽管在这个特定示例中使用多对多关系似乎是一种开销,但对于我当前的任务至关重要。

如何在作者实体中更改 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的Serializer组件,一个很好的指南可以在这里找到 https://thomas.jarrand.fr/blog/serialization/

或者也许使用JMSSerializer。

编辑

DQL 可能如下所示:

$authors = $this->getEntityManager()->createQuery('
SELECT author, books
FROM AppBundleEntityAuthor author
JOIN author.books books
')->getResult();

相关内容

  • 没有找到相关文章

最新更新