首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在JSON中使用OneToMany关联中的原则集数据

在JSON中使用OneToMany关联中的原则集数据
EN

Stack Overflow用户
提问于 2018-11-11 20:23:52
回答 1查看 987关注 0票数 2

我看到了许多如何在实体之间建立OneToMany关联的例子。但是,我还没有看到任何关于如何从关联中输出数据的内容。(例如转换为JSON或只拥有一个干净的数组)

下面是一些示例代码:

代码语言:javascript
复制
declare(strict_types=1);

namespace Banks\Entity;

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

/**
 * https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/basic-mapping.html
 *
 * @ORM\Entity
 * @ORM\Table(name="bank")
 **/
class Banks implements \JsonSerializable
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer", name="id", nullable=false)
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $id;

    /**
     * A Bank could have Many Branches
     *
     * @ORM\OneToMany(targetEntity="Branches\Entity\Branches", mappedBy="bank")
     *
     */
    protected $branches;

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    protected $name;

    /**
     *
     * @return array|mixed
     */
    public function jsonSerialize()
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'branches' => $this->getBranches()
        ];
    }

    public function __construct()
    {
        $this->branches = new ArrayCollection();
    }

    public function getBranches(): Collection
    {
        return $this->branches;
    }

    // ... Other getter/setters removed
}

然后我们也有了分支实体:

代码语言:javascript
复制
declare(strict_types=1);

namespace Branches\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/basic-mapping.html
 *
 * @ORM\Entity
 * @ORM\Table(name="branches")
 **/
class Branches implements \JsonSerializable
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer", nullable=false)
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $id;

    /**
     * A Branch has one Bank
     *
     * @ORM\ManyToOne(targetEntity="Banks\Entity\Banks", inversedBy="branches")
     * @ORM\JoinColumn(name="bank_id", referencedColumnName="id")
     */
    protected $bank;

    /**
     * @ORM\Column(type="integer", nullable=false)
     */
    protected $bank_id;

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    protected $name;

    /**
     *
     * @return array|mixed
     */
    public function jsonSerialize()
    {
        return [
            'id' => $this->id,
            'bank_id' => $this->bank_id,
            'name' => $this->name,
            'bank' => $this->getBank()
        ];
    }

    public function getBank()
    {
        return $this->bank;
    }

    // ... Other getter/setters removed
}

查询两个实体总体上运行良好,调用$result->jsonSerialize(),然后使用return new JsonResponse($result)返回以获得JSON对象。尽管查询分支具有预期的结果,但作为输出的一部分,我将分行与关联银行一起接收到,但对银行的查询没有返回关联分行,而是显示为"branches": {}

我知道这是因为$branches是一个集合,但是如何以一种方式输出它以成为结果JSON对象的一部分?

我尝试过$this->branches->toArray(),但是这会导致一个不能编码为JSON的对象数组,因此,结果是一个错误。

注意:$this->getBranches()的内容(对象)确实按照预期包含分支,$this->branches->count()可以看到这些分支。但是,如何以允许JsonSerializable创建JSON的方式联系它们呢?

根据请求,下面是留给实体使用的中间件代码:

工厂用于创建Handler所需的内容:

代码语言:javascript
复制
class BanksViewHandlerFactory
{
    public function __invoke(ContainerInterface $container) : BanksViewHandler
    {
        $entityManager = $container->get(EntityManager::class);

        $entityManager->getConfiguration()->addEntityNamespace('Banks', 'Banks\Entity');

        $entityRepository = $entityManager->getRepository('Banks:Banks');

        return new BanksViewHandler($entityManager, $entityRepository);
    }
}

工厂调用Handler:

代码语言:javascript
复制
class BanksViewHandler implements RequestHandlerInterface
{
    protected $entityManager;
    protected $entityRepository;

    public function __construct(
        EntityManager $entityManager,
        EntityRepository $entityRepository,
    ) {
        $this->entityManager = $entityManager;
        $this->entityRepository = $entityRepository;
    }

    public function handle(ServerRequestInterface $request) : ResponseInterface
    {
        $return = $this->entityRepository->find($request->getAttribute('id'));

$result['Result']['Banks'] = $return->jsonSerialize();

        return new JsonResponse($result);
    }
}

处理程序返回JSON。

EN

回答 1

Stack Overflow用户

发布于 2018-11-11 21:03:35

需要注意的是,在实现\JsonSerializable接口时,直接调用jsonSerialize()并不会返回JSON,也不会显式调用此方法。

如文件中所述:

实现JsonSerializable的对象在使用json_encode()编码时可以自定义它们的JSON表示。

实现此接口的目的是强制执行jsonSerialize()方法,在将对象传递给json_encode()时内部调用该方法;例如:

代码语言:javascript
复制
$result = $banksRepository->find($id);
$json = json_encode($result);

此外,如果还想序列化子分支实体,则需要:

  1. 为这个实体实现\JsonSerializable (您已经完成了)
  2. 原则将这些分支作为一个ArrayCollection对象返回,包含所有子分支对象。为了确保json_encode()正确地将这些代码编码为JSON,需要使用toArray()ArrayCollection转换为数组。

为了说明-(正如您所指出的,您也实现了这一点):

代码语言:javascript
复制
public function jsonSerialize()
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'branches' => $this->getBranches()->toArray(), // <-- 
    ];
}

这将像预期的那样序列化您的银行和相关分行实体。希望这会有所帮助:)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53252889

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档