нормализатор api-платформы: преобразование Id объекта в HashId во время выполнения без сохранения - PullRequest
0 голосов
/ 14 января 2019

Я работаю над API Platform. В настоящее время я пытаюсь реализовать это https://github.com/ivanakimov/hashids.php

, выполнив шаги в https://github.com/api-platform/api-platform/issues/724#issuecomment-398812438

однако я не могу передать сущность в моем сериализаторе. Я могу получить только отдельные свойства, которые будут переданы.

Моя сущность:

class MyEntity
{
/**
 * @var int
 * @ORM\Column(name="id", type="integer", nullable=false)
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="IDENTITY")
 */
private $id;

/**
 * @var string|null
 *
 * @ORM\Column(name="message", type="text", length=0, nullable=true)
 */
private $message;

/**
 * @return int
 */
public function getId(): int
{
    return $this->id;
}

/**
 * @param $id
 */
public function setId($id): void
{
    $this->id = $id;
}

/**
 * @return string|null
 */
public function getMessage(): ?string
{
    return $this->message;
}

/**
 * @param string|null $message
 */
public function setMessage(?string $message): void
{
    $this->message = $message;
}
}

services.yaml:

'App\Serializer\CommonIdentifierNormalizer': tags: [ name: serializer.normalizer ]

CommonIdentifierNormalizer:

namespace App\Serializer;

use Hashids\Hashids;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;

class CommonIdentifierNormalizer implements NormalizerInterface
{
 private $normalizer;

public function __construct(ObjectNormalizer $objectNormalizer)
{
    $this->normalizer = $objectNormalizer;
}

public function normalize($object, $format = null, array $context = array())
{
    $hashId = new Hashids('', 7);
    $data = $hashId->encodeHex($object->getId());

    $object->setId($data);

    return $this->normalizer->normalize($object);
}

public function supportsNormalization($data, $format = null)
{
    return is_object($data);
}
}

Однако даже метод supportNormalization не работает, поскольку передаются только отдельные свойства. Я хотел бы сделать это глобальным решением, где все свойства, отмеченные как идентификаторы, нормализованы, и мой запрос принимает хеш-коды вместо первичного ключа. Вы можете помочь мне с этим?

Ответы [ 2 ]

0 голосов
/ 13 июля 2019

Вот решение с JMS Serializer, использующее событие pre_serialize.

При использовании этого метода фактический идентификатор исключается из сериализации, но мы используем это событие для добавления атрибута hashId к нашей сущности, который не сохраняется.

Общая черта:

namespace App\Entity\Traits;

use JMS\Serializer\Annotation as Serializer;

trait HashIdTrait
{
    /**
     * @var string
     * @Serializer\Accessor(getter="getHashId")
     */
    private $hashId;

    /**
     * @return string
     */
    public function getHashId(): ?string
    {
        return $this->hashId;
    }

    /**
     * @param mixed $hashId
     *
     * @return self
     */
    public function setHashId($hashId): self
    {
        $this->hashId = $hashId;

        return $this;
    }
}

Организация:

namespace App\Entity;

use App\Entity\Traits\HashIdTrait;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as Serializer;

/**
 * @ORM\Entity()
 */
class Entity
{
    use HashIdTrait;

    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     * @Serializer\Exclude()
     */
    private $id;

    [...]

Событие сериализатора:

namespace App\Serializer\Event;

use App\Entity\Entity;
use App\Service\HashIds;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\ObjectEvent;

class HashIdEvent implements EventSubscriberInterface
{
    /** @var HashIds */
    protected $hashIds;

    /** @required */
    public function setHashIds(HashIds $hashIds)
    {
        $this->hashIds = $hashIds;
    }

    public static function getSubscribedEvents()
    {
        return [
            [
                'event' => 'serializer.pre_serialize',
                'class' => Entity::class,
                'method' => 'onPreSerialize',
            ]
        ];
    }

    public function onPreSerialize(ObjectEvent $event)
    {
        $entity = $event->getObject();
        $entity->setHashId($this->hashIds->encode($entity->getId()));
    }
}
0 голосов
/ 25 января 2019

как обновление. Я попробовал это с использованием идентификатора нормализатора и денормализатора, и он работал отлично.

мой рабочий пример.

services.yaml

App\Serializer\CommonIdentifierNormalizer:
    tags: ['serializer.normalizer']
    decorates: 'api_platform.jsonld.normalizer.item'
    arguments:
        $decorated: '@App\Serializer\CommonIdentifierNormalizer.inner'
        $iriConverter: '@ApiPlatform\Core\Api\IriConverterInterface'

App\Serializer\CommonIdentifierDenormalizer:
    tags:
        - { name: api_platform.identifier.denormalizer }

Denormaliser

final class CommonIdentifierDenormalizer implements DenormalizerInterface
{
/**
 * @param mixed $data
 * @param string $class
 * @param null $format
 * @param array $context
 * @return mixed|object|string
 */
public function denormalize($data, $class, $format = null, array $context = [])
{
    if (is_string($data)) {
        return IdentifierHelper::reverseTransformHashToId($data);
    }
    return $data;
}

/**
 * @param mixed $data
 * @param string $type
 * @param null $format
 * @return bool
 */
public function supportsDenormalization($data, $type, $format = null)
{
    return is_string($data);
}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...