Php 在JSON中使用来自OneToMany协会的条令收集数据

Php 在JSON中使用来自OneToMany协会的条令收集数据,php,doctrine-orm,doctrine,Php,Doctrine Orm,Doctrine,我已经看到了很多关于如何在实体之间建立一个单一的关联的例子。但是,我没有看到任何关于如何从关联输出数据的内容。(例如转换为JSON或只是拥有一个干净的数组) 下面是一些示例代码: declare(strict_types=1); namespace Banks\Entity; use Doctrine\ORM\Mapping as ORM; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collect

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

下面是一些示例代码:

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
}
然后我们还有分支机构实体:

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()
,然后返回
returnnewjsonresponse($result)
以获取JSON对象。尽管查询分支机构会得到预期的结果,其中我会收到分支机构以及作为输出一部分的关联银行,但对银行的查询不会返回关联的分支机构,而是只显示为
“分支机构”:{}

我知道这是因为
$branchs
是一个集合,但如何将其输出为结果JSON对象的一部分呢

我尝试了
$this->branchs->toArray()
,但这会导致一个无法编码为JSON的对象数组,因此以错误告终

注意:
$this->getbranchs()
的内容(对象)确实包含预期的分支,这可以通过
$this->branchs->count()看到。但是,如何以这种方式接触到它们,从而允许JsonSerializable创建JSON呢

根据要求,以下是中间件代码,由实体使用决定:

工厂用于创建处理程序所需的内容:

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);
    }
}
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);
    }
}
工厂调用处理程序:

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);
    }
}
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。

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

如文件所述:

当使用JSON_encode()编码时,实现JsonSerializable的对象可以自定义其JSON表示

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

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

  • 为此实体实现
    \JsonSerializable
    (您已经完成)
  • 条令将这些分支作为
    ArrayCollection
    对象返回,其中包含所有子分支对象。为了确保
    json\u encode()
    正确地将它们编码为json,您需要使用
    toArray()
    ArrayCollection
    转换为数组
  • 为了说明(正如您指出的,您也实现了这一点):

    公共函数jsonSerialize()
    {
    返回[
    'id'=>this->id,
    “名称”=>$this->name,
    
    'branchs'=>$this->getbranchs()->toArray(),//您在哪里尝试了
    $this->branchs->toArray()
    -in
    Banks::jsonSerialize()
    ?另外-您是否直接调用
    $result->jsonSerialize()
    当您将对象传递给
    json_encode()
    ;即:
    $json=json_encode(%$result);
    。是的,我尝试了
    $this->branchs->toArray()
    作为
    getbranchs()
    的返回,也尝试了
    Banks::jsonSerialize()
    作为`$this->getbranchs()->toArray()。好的,这应该是正确的。然后您是否将结果传递到
    json\u encode()
    以将对象转换为json?因此,您是说正确的用法是仍然使用json\u encode($result)?我不知道,它正在按预期工作并返回JSON。这是我第一次使用
    JsonSerializable
    。这样做会返回一个错误。
    InvalidArgumentException:无法将数据编码为JSON
    是否可以更新您的问题以包括一些控制器代码?添加了HandlerFactory和Handler。没有MVC;-)