Last active
August 6, 2021 20:52
-
-
Save artyuum/6405566cf7fde3dc6182bf2557021b59 to your computer and use it in GitHub Desktop.
A ParamConverter to use HashIds with Doctrine + Symfony.
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\ParamConverter; | |
use Doctrine\ORM\EntityManagerInterface; | |
use Hashids\HashidsInterface; | |
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; | |
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface; | |
use Symfony\Component\HttpFoundation\Request; | |
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; | |
use Symfony\Component\PropertyAccess\PropertyAccessorInterface; | |
use Throwable; | |
class HashidsDoctrineParamConverter implements ParamConverterInterface | |
{ | |
public function __construct( | |
private HashidsInterface $hashids, private EntityManagerInterface $entityManager, private PropertyAccessorInterface $propertyAccessor | |
) { | |
} | |
public function supports(ParamConverter $configuration) | |
{ | |
// supports by default | |
if (!isset($configuration->getOptions()['hashids_doctrine'])) { | |
return true; | |
} | |
return $configuration->getOptions()['hashids_doctrine']; | |
} | |
public function apply(Request $request, ParamConverter $configuration) | |
{ | |
$routeParams = $request->attributes->get('_route_params'); | |
$parameterName = $configuration->getName(); | |
$parameterValue = $request->attributes->get($parameterName); | |
$class = $configuration->getClass(); | |
if (!$configuration->getClass()) { | |
return; | |
} | |
// ensures that the parameter exists in the route params | |
if (!$routeParams || !in_array($parameterName, array_keys($routeParams), true)) { | |
return; | |
} | |
// ends here if the class is not an entity | |
try { | |
$repository = $this->entityManager->getRepository($class); | |
} catch (Throwable) { | |
return; | |
} | |
if (property_exists($class, $parameterName)) { | |
$entity = $repository->findOneBy([ | |
$parameterName => $parameterValue, | |
]); | |
// ends here if the entity couldn't be found | |
if (!$entity) { | |
throw new NotFoundHttpException(sprintf('%s object not found by the property "%s" with the value "%s".', $class, $parameterName, $parameterValue)); | |
} | |
// replaces the parameter value by the entity | |
$request->attributes->set($parameterName, $entity); | |
return; | |
} | |
// decodes the encoded ID | |
$decodedId = $this->hashids->decode($parameterValue); | |
// ends here if the ID couldn't be decoded | |
if (empty($decodedId)) { | |
throw new NotFoundHttpException(sprintf('The passed ID "%s" could not be decoded.', $parameterValue)); | |
} | |
$decodedId = current($decodedId); | |
$entity = $repository->find($decodedId); | |
// ends here if the entity couldn't be found | |
if (!$entity) { | |
throw new NotFoundHttpException(sprintf('%s object not found by ID: %s (%s)', $class, $decodedId, $parameterValue)); | |
} | |
// replaces the parameter value by the entity | |
$request->attributes->set($parameterName, $entity); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I had to make my own ParamConverter because hashids-bundle is not properly working in my app.
Usage
The ParamConverter will be automatically used but if you want to disable it, just do it like that: