Last active
April 21, 2021 22:10
-
-
Save allucardster/86073426076bc49822a9f488d6cc26ff to your computer and use it in GitHub Desktop.
JMS Serializer Subscriber example with Symfony 4.4
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Controller\Api; | |
use App\Repository\ProductRepository; | |
use FOS\RestBundle\Controller\AbstractFOSRestController; | |
use FOS\RestBundle\View\View; | |
use Symfony\Component\HttpFoundation\Response; | |
use FOS\RestBundle\Controller\Annotations as Rest; | |
/** | |
* @Rest\Route("/product") | |
*/ | |
class ProductController extends AbstractFOSRestController | |
{ | |
/** | |
* @var ProductRepository | |
*/ | |
private ProductRepository $repository; | |
/** | |
* ProductController constructor. | |
* @param ProductRepository $repository | |
*/ | |
public function __construct(ProductRepository $repository) | |
{ | |
$this->repository = $repository; | |
} | |
/** | |
* @Rest\Get("/") | |
* @Rest\View(serializerGroups={"Default", "product_stock"}) | |
* | |
* @return View | |
*/ | |
public function getAction(): View | |
{ | |
$products = $this->repository->findAll(); | |
return View::create($products, Response ::HTTP_OK); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Entity; | |
use Doctrine\ORM\Mapping as ORM; | |
use JMS\Serializer\Annotation as Serializer; | |
/** | |
* @ORM\Entity(repositoryClass="App\Repository\ProductRepository") | |
* @Serializer\ExclusionPolicy("all") | |
*/ | |
class Product | |
{ | |
/** | |
* @ORM\Id() | |
* @ORM\GeneratedValue() | |
* @ORM\Column(type="integer") | |
* @Serializer\Expose() | |
*/ | |
private int $id; | |
/** | |
* @ORM\Column(type="string", length=255) | |
* @Serializer\Expose() | |
*/ | |
private string $name; | |
/** | |
* @ORM\Column(type="string", length=255) | |
*/ | |
private string $brand; | |
/** | |
* @ORM\Column(type="float", options={"default":0}) | |
*/ | |
private float $price; | |
public function getId(): int | |
{ | |
return $this->id; | |
} | |
public function getName(): string | |
{ | |
return $this->name; | |
} | |
public function setName(string $name): self | |
{ | |
$this->name = $name; | |
return $this; | |
} | |
public function getBrand(): string | |
{ | |
return $this->brand; | |
} | |
public function setBrand(string $brand): self | |
{ | |
$this->brand = $brand; | |
return $this; | |
} | |
public function getPrice(): float | |
{ | |
return $this->price; | |
} | |
public function setPrice(float $price): self | |
{ | |
$this->price = $price; | |
return $this; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Serializer\Subscriber; | |
use App\Entity\Product; | |
use App\Util\BrandType; | |
use App\Util\OffPrice; | |
use JMS\Serializer\Context; | |
use JMS\Serializer\EventDispatcher\EventSubscriberInterface; | |
use JMS\Serializer\EventDispatcher\ObjectEvent; | |
use JMS\Serializer\JsonSerializationVisitor; | |
use JMS\Serializer\Metadata\StaticPropertyMetadata; | |
class ProductSubscriber implements EventSubscriberInterface | |
{ | |
/** | |
* Returns the events to which this class has subscribed. | |
* | |
* Return format: | |
* array( | |
* array('event' => 'the-event-name', 'method' => 'onEventName', 'class' => 'some-class', 'format' => 'json'), | |
* array(...), | |
* ) | |
* | |
* The class may be omitted if the class wants to subscribe to events of all classes. | |
* Same goes for the format key. | |
* | |
* @return array | |
*/ | |
public static function getSubscribedEvents() | |
{ | |
return [ | |
[ | |
'event' => 'serializer.post_serialize', | |
'method' => 'onPostSerialize', | |
'class' => Product::class, | |
'format' => 'json', | |
], | |
]; | |
} | |
/** | |
* @param Context $context | |
* @param string $group | |
* | |
* @return bool | |
*/ | |
private function isGroupActive(Context $context, string $group): bool | |
{ | |
$groups = $context->hasAttribute('groups') ? $context->getAttribute('groups') : []; | |
return in_array($group, $groups); | |
} | |
/** | |
* @param JsonSerializationVisitor $visitor | |
* @param string $key | |
* @param $value | |
*/ | |
private function addData(JsonSerializationVisitor $visitor, string $key, $value) | |
{ | |
$visitor->visitProperty(new StaticPropertyMetadata('', $key, $value), $value); | |
} | |
/** | |
* @param ObjectEvent $event | |
* @throws \ReflectionException | |
*/ | |
public function onPostSerialize(ObjectEvent $event) | |
{ | |
/** @var Product $product */ | |
$product = $event->getObject(); | |
$context = $event->getContext(); | |
/** @var JsonSerializationVisitor $visitor */ | |
$visitor = $event->getVisitor(); | |
// Add brand node | |
$this->addData($visitor, 'brand', [ | |
'id' => $product->getBrand(), | |
'name' => BrandType::getName($product->getBrand()), | |
]); | |
// Add price node | |
$this->addData($visitor, 'price', OffPrice::getPrice($product->getBrand(), $product->getPrice())); | |
// Add stock node | |
if ($this->isGroupActive($context, 'product_stock')) { | |
$this->addData($visitor, 'stock', 100); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//GET /api/product/ | |
[ | |
{ | |
"id": 1, | |
"name": "Product Name 1", | |
"brand": "Brand Name 1", //<-- node added by default from `ProductSubscriber` | |
"price": "99.99", //<-- node added by default from `ProductSubscriber` | |
"stock": 100 //<-- node added from `ProductSubscriber` if `product_stock` serialization group is used | |
} | |
] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment