Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save hriad/1f36492385ad7b8f341e80db3fd44d10 to your computer and use it in GitHub Desktop.
Save hriad/1f36492385ad7b8f341e80db3fd44d10 to your computer and use it in GitHub Desktop.
A ParamConverter to use HashIds with Doctrine + Symfony.
<?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