Skip to content

Instantly share code, notes, and snippets.

@nuryagdym
Last active June 20, 2021 09:17
Show Gist options
  • Save nuryagdym/1b9ea52dbb92c1b4481c22b4ee49aa97 to your computer and use it in GitHub Desktop.
Save nuryagdym/1b9ea52dbb92c1b4481c22b4ee49aa97 to your computer and use it in GitHub Desktop.
How to use Symfony Serializer Component to Normalize Phalcon PHP models
<?php
namespace App\Model;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\MaxDepth;
use Doctrine\Common\Annotations\Annotation\IgnoreAnnotation;
/**
* @IgnoreAnnotation("Primary")
* @IgnoreAnnotation("Identity")
* @IgnoreAnnotation("Column")
*/
class Address extends \Phalcon\Mvc\Model
{
/**
* @var int|null
* @Primary
* @Identity
* @Column(type="integer", length=11, nullable=false)
* @Groups({"list", "detail"})
*/
private $id;
/**
*
* @var string|null
* @Column(type="string", length=255, nullable=false)
* @Groups({"list", "detail"})
*/
private $street;
/**
* Initialize method for model.
*/
public function initialize()
{
$this->hasOne('id', User::class, 'address_id', ['alias' => 'user']);
}
public function getId(): ?int
{
return $this->id;
}
public function getStreet(): ?string
{
return $this->street;
}
/**
* @Groups({"detail"})
* @return User|null
*/
public function getUser(): ?User
{
return $this->user ? $this->user : null;
}
}
<?php
namespace App\Controller;
use Phalcon\Mvc\Controller;
use App\Serializer\Normalizer\ModelNormalizer;
use App\Model\User;
class IndexController extends Controller
{
public function testNormalizerAction()
{
$user = User::findFirst();
$normalizer = new ModelNormalizer();
$normalizedItem = $normalizer->normalize($user, null, ['groups' => 'list']);
//or $normalizedItem = $normalizer->normalize($user, null, ['groups' => 'detail']);
//or $normalizedItem = $normalizer->normalize($user, null, ['groups' => ['detail', 'list']]);
return json_encode($normalizedItem);
}
}
<?php
namespace App\Serializer\Normalizer;
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\Serializer\Exception\ExceptionInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
class ModelNormalizer implements NormalizerInterface
{
/**
* also converts camel cases to snake cases
* @param mixed $data
* @param string|null $format
* @param array $context
* @return array|\ArrayObject|bool|\Countable|float|int|mixed|string|\Traversable|null
* @throws ExceptionInterface
*/
public function normalize($data, string $format = null, array $context = [])
{
$defaultContext = [
AbstractObjectNormalizer::ENABLE_MAX_DEPTH => true,
AbstractObjectNormalizer::MAX_DEPTH_HANDLER => function ($innerObject, $outerObject, string $attributeName, string $format = null, array $context = []) {
return null;
},
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => function ($object, $format, $context) {
return null;
},
];
$defaultContext[AbstractObjectNormalizer::GROUPS] = $context['groups'];
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$normalizer = new ObjectNormalizer($classMetadataFactory, null, null, null, null, null, $defaultContext);
$serializer = new Serializer([$normalizer]);
return $serializer->normalize($data);
}
public function supportsNormalization($data, string $format = null)
{
return true;
}
}
<?php
namespace App\Model;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\MaxDepth;
use Doctrine\Common\Annotations\Annotation\IgnoreAnnotation;
/**
* @IgnoreAnnotation("Primary")
* @IgnoreAnnotation("Identity")
* @IgnoreAnnotation("Column")
*/
class User extends \Phalcon\Mvc\Model
{
/**
* @var int|null
* @Primary
* @Identity
* @Column(type="integer", length=11, nullable=false)
* @Groups({"list", "detail"})
*/
private $id;
/**
* @var int|null
* @Column(type="integer", length=11, nullable=true)
* @Groups({"list", "detail"})
*/
private $address_id;
/**
*
* @var string|null
* @Column(type="string", length=30, nullable=false)
* @Groups({"list", "detail"})
*/
private $username;
/**
* Initialize method for model.
*/
public function initialize()
{
$this->hasOne('address_id', Address::class, 'id', ['alias' => 'address']);
}
public function getId(): ?int
{
return $this->id;
}
public function getAddressId(): ?int
{
return $this->address_id;
}
public function getUsername(): ?string
{
return $this->username;
}
/**
* @Groups({"detail"})
* @MaxDepth(1)
*/
public function getAddress(): ?Address
{
return $this->address ? $this->address : null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment