Использование данных коллекции Doctrine от ассоциации OneToMany в JSON

Я видел много примеров того, как установить связь между сущностями OneToMany. Тем не менее, я не видел ничего о том, как выводить данные из ассоциации. (например, преобразование в 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()затем возвращаясь с return new JsonResponse($result) чтобы получить объект JSON. Хотя запрос Филиала имеет ожидаемый результат, когда я получаю Филиал вместе с ассоциированным Банком как часть выходных данных, запрос к Банку не возвращает ассоциированные Филиалы, а вместо этого отображается только как "branches": {}

Я знаю это потому что $branches такое коллекция, но как вывести ее таким образом, чтобы она была частью результирующего объекта JSON?

я пробовал $this->branches->toArray(), но это приводит к массиву объектов, которые не могут быть закодированы в JSON, поэтому заканчивается ошибкой.

ПРИМЕЧАНИЕ: содержание (объект) $this->getBranches() содержит ветки, как и ожидалось, что можно увидеть $this->branches->count(), Но как связаться с ними таким образом, чтобы JsonSerializable мог создать JSON?

В соответствии с запросом приведен код промежуточного программного обеспечения, оставляемый до использования Entity:

Фабрика используется для создания того, что требуется обработчику:

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.

2

Решение

Важно отметить, что при реализации \JsonSerializable интерфейс, вызов jsonSerialize() напрямую не возвращает JSON, и вы не вызываете этот метод явно.

Как указано в документах:

Объекты, реализующие JsonSerializable, могут настроить свое представление JSON при кодировании с помощью json_encode ().

Целью реализации этого интерфейса является обеспечение соблюдения jsonSerialize() метод, который вызывается внутри при передаче объекта (ов) json_encode(); например:

$result = $banksRepository->find($id);
$json = json_encode($result);

Кроме того, если вы хотите также сериализовать дочерние сущности Branch, вам необходимо:

  1. Воплощать в жизнь \JsonSerializable для этой сущности (что вы сделали)
  2. Доктрина вернет эти Ветви как ArrayCollection объект, содержащий все дочерние объекты Branch. Чтобы гарантировать, что json_encode() кодирует их в JSON правильно, вам нужно преобразовать ArrayCollection в массив с помощью toArray(),

Чтобы проиллюстрировать — (как вы указали, вы также реализовали это):

public function jsonSerialize()
{
return [
'id' => $this->id,
'name' => $this->name,
'branches' => $this->getBranches()->toArray(), // <--
];
}

Это должно сериализовать ваш Банк и связанные с ним филиалы в соответствии с ожиданиями. Надеюсь это поможет 🙂

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector