Symfony - Doctrine:设计REST api以接收多个到多个实体

时间:2017-07-29 19:11:26

标签: php symfony doctrine-orm orm

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

  

作者实体:

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

图书实体:

<?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"
                }
            ]
        }
        ]
}

使用这样的休息控制器:

/**
 * @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表示保存为附加作者表的列。
  3. 但他们两个在我看来有点hacky。我该怎么办?

    请注意,这是我想要实现的简化表示。虽然对于这个特定的例子采用多对多关系似乎是一个开销,但对我当前的任务至关重要。

1 个答案:

答案 0 :(得分: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中的Serializer组件,可以在此处找到一个很棒的指南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();