В документации есть опция "deserialize"= false
. Это означает, что для этой операции десериализация не произойдет. Следовательно, вы должны записать весь процесс десериализации самостоятельно в контроллер обработчика. Вы также должны написать поля для документации по чванству.
Например:
<?php
declare(strict_types=1);
namespace App\Entity;
// more use...
/**
* @ApiResource(
* iri="http://schema.org/MediaObject",
* normalizationContext={
* "groups" = {"media:read"}
* },
* collectionOperations={
* "post" = {
* "controller" = MediaHandler::class,
* "deserialize" = false,
* "access_control" = "is_granted('ROLE_USER')",
* "validation_groups" = {"Default", "media:collection:post"},
* "openapi_context" = {
* "requestBody" = {
* "content" = {
* "multipart/form-data" = {
* "schema" = {
* "type" = "object",
* "properties" = {
* "file" = {
* "type" = "string",
* "format" = "binary"
* },
* "name" = {
* "type" = "string"
* }
* }
* }
* }
* }
* }
* }
* },
* "get"
* },
* itemOperations={
* "get"
* }
* )
* @Vich\Uploadable
* @ORM\Entity(repositoryClass="App\Repository\MediaRepository")
*/
class Media
{
/**
* @ApiProperty(iri="http://schema.org/contentUrl")
* @Groups({"media:read"})
*/
public $contentUrl;
/**
* @Assert\NotNull(groups={"media:collection:post"})
* @Vich\UploadableField(mapping="media", fileNameProperty="filePath")
* @Assert\File(
* maxSize="2M",
* mimeTypes={
* "application/pdf",
* "application/x-pdf",
* "image/jpeg",
* "image/jpg",
* "image/png"
* },
* groups={"media:collection:post"}
* )
*/
public $file;
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=512)
*/
private $filePath;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
//...
}
Пример обработчика контроллера:
<?php
declare(strict_types=1);
namespace App\Controller\Api;
// use ...
class MediaHandler extends AbstractController
{
/**
* @var EntityManagerInterface
*/
private EntityManagerInterface $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
public function __invoke(Request $request): Media
{
$uploadedFile = $request->files->get('file');
if (!$uploadedFile) {
throw new BadRequestHttpException('"file" is required');
}
$mediaObject = new Media();
$mediaObject->file = $uploadedFile;
$mediaObject->setName($request->request->get('name'));
return $mediaObject;
}
}
Если существует «Книга». И вы хотите добавить Book
к MediaObject
, вы можете установить строку iri и проанализировать ее в контроллере-обработчике:
//...
public function __construct(EntityManagerInterface $entityManager, IriConverterInterface $iriConverter)
{
$this->entityManager = $entityManager;
$this->iriConverter = $iriConverter;
}
public function __invoke(Request $request): Media
{
$uploadedFile = $request->files->get('file');
if (!$uploadedFile) {
throw new BadRequestHttpException('"file" is required');
}
$iriBook = $request->request->get('book');
$book = null;
if ($iriBook) {
/**
* @var Book $book
*/
$book = $this->iriConverter->getItemFromIri($iriBook);
}
$mediaObject = new Media();
$mediaObject->file = $uploadedFile;
$mediaObject->setBook($book);
return $mediaObject;
}
//..
Если это ваш случай, то никаких дальнейших действий (DataPersist
) требуется.
Далее вам нужно go https://api-platform.com/docs/core/data-persisters/ и сделать обработчик DataPesist
Пример:
<?php
declare(strict_types=1);
namespace App\DataPersister;
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
use App\Entity\Media;
use App\ExtendTrait\ContextAwareDataTrait;
use Doctrine\ORM\EntityManagerInterface;
class MediaObjectDataPersister implements ContextAwareDataPersisterInterface
{
use ContextAwareDataTrait;
/**
* @var EntityManagerInterface
*/
private EntityManagerInterface $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
/**
* {@inheritdoc}
*/
public function supports($data, array $context = []): bool
{
return $this->isCollection('post', $context) && $data instanceof Media;
}
/**
* {@inheritdoc}
*
* @param $data Media
*
* @throws \Exception
*/
public function persist($data, array $context = []): void
{
$book = new Book();
$book->setName($data->getName());
// begin transaction and persist and flush $book and $data
}
/**
* {@inheritdoc}
*/
public function remove($data, array $context = []): void
{
// todo remove book
}
}
PS Я не проверяю этот код. Я пишу идею;) PSS $this->isCollection()
Это функция от моей черты, может быть, вам это нужно:
<?php
declare(strict_types=1);
namespace App\ExtendTrait;
/**
* Trait ContextAwareDataTrait.
*
* Helps confirm the operation name
*/
trait ContextAwareDataTrait
{
public function isItem(string $operationName, array $context, string $resourceClass = null): bool
{
if ($resourceClass && ($context['resource_class'] ?? false) !== $resourceClass) {
return false;
}
return ($context['item_operation_name'] ?? null) === $operationName;
}
public function isCollection(string $operationName, array $context, string $resourceClass = null): bool
{
if ($resourceClass && ($context['resource_class'] ?? false) !== $resourceClass) {
return false;
}
return ($context['collection_operation_name'] ?? null) === $operationName;
}
}