Skip to content

Instantly share code, notes, and snippets.

@brunodplima
Forked from weaverryan/Link.php
Last active October 26, 2016 21:48
Show Gist options
  • Save brunodplima/2f984535556c959327a6730f3e89e93c to your computer and use it in GitHub Desktop.
Save brunodplima/2f984535556c959327a6730f3e89e93c to your computer and use it in GitHub Desktop.
KnpUniversity Symfony REST: Using @link with the PaginatedCollection (http://knpuniversity.com/screencast/symfony-rest3/evaluating-expression)
<?php
namespace AppBundle\Serializer;
use AppBundle\Annotation\Link;
use Doctrine\Common\Annotations\Reader;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\ObjectEvent;
use JMS\Serializer\JsonSerializationVisitor;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\Routing\RouterInterface;
class LinkSerializationSubscriber implements EventSubscriberInterface
{
private $router;
private $annotationReader;
private $expressionLanguage;
public function __construct(RouterInterface $router, Reader $annotationReader)
{
$this->router = $router;
$this->annotationReader = $annotationReader;
$this->expressionLanguage = new ExpressionLanguage();
}
public function onPostSerialize(ObjectEvent $event)
{
/** @var JsonSerializationVisitor $visitor */
$visitor = $event->getVisitor();
$object = $event->getObject();
$annotations = $this->annotationReader
->getClassAnnotations(new \ReflectionObject($object));
$links = array();
foreach ($annotations as $annotation) {
if ($annotation instanceof Link) {
if ($annotation->url) {
$uri = $this->evaluate($annotation->url, $object);
} else {
$uri = $this->router->generate(
$annotation->route,
$this->resolveParams($annotation->params, $object)
);
}
// allow a blank URI to be an optional link
if ($uri) {
$links[$annotation->name] = $uri;
}
}
}
$visitor->addData('_links', $links);
}
private function resolveParams(array $params, $object)
{
foreach ($params as $key => $param) {
$params[$key] = $this->evaluate($param, $object);
}
return $params;
}
private function evaluate($expression, $object)
{
return $this->expressionLanguage
->evaluate($expression, array('object' => $object));
}
public static function getSubscribedEvents()
{
return array(
array(
'event' => 'serializer.post_serialize',
'method' => 'onPostSerialize',
'format' => 'json',
)
);
}
}
<?php
namespace AppBundle\Pagination;
use JMS\Serializer\Annotation as Serializer;
use AppBundle\Annotation\Link;
/**
* @Link(
* "self",
* url = "object.getUrl('self')"
* )
* @Link(
* "next",
* url = "object.getUrl('next')"
* )
* @Link(
* "prev",
* url = "object.getUrl('prev')"
* )
* @Link(
* "first",
* url = "object.getUrl('first')"
* )
* @Link(
* "last",
* url = "object.getUrl('last')"
* )
*/
class PaginatedCollection
{
private $items;
private $total;
private $count;
/**
* @Serializer\Exclude()
* @var array
*/
private $links = array();
public function __construct(array $items, $totalItems)
{
$this->items = $items;
$this->total = $totalItems;
$this->count = count($items);
}
public function addLink($ref, $url)
{
$this->links[$ref] = $url;
}
public function getUrl($ref)
{
return isset($this->links[$ref]) ? $this->links[$ref] : '';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment