Last active
September 19, 2025 06:01
-
-
Save mattattui/efd1c4470f2ce0097fb5 to your computer and use it in GitHub Desktop.
Revisions
-
mattattui revised this gist
Mar 7, 2015 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,7 +1,7 @@ # Using Tiny (ID obfuscator) with Symfony2's ParamConverters * Symfony's convenience methods for automatically fetching database entities from URL parameters are super-handy. * Obfuscated/hash IDs are a great idea, especially in APIs (where you aren't concerned with SEO, but might be concerned about sequential numeric ids or exposing database information). * Here's how to make them work together. The stuff in this gist sets up a Twig filter (`obfuscate`) to create the obfuscated ids (for URLs), makes the obfuscator available as a service (`id_obfuscator`) so you can also generate obfuscated URLs in your controllers or whatever, and extends the DoctrineParamConverter to allow it to retrieve entities by their deobfuscated id. -
mattattui revised this gist
Mar 7, 2015 . 5 changed files with 54 additions and 12 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,11 +1,26 @@ # Using Tiny (ID obfuscator) with Symfony2's ParamConverters * Symfony's convenience methods for automatically fetching database entities from URL parameters are super-handy. * Obfuscated/hash IDs are a great idea, especially in APIs where you aren't concerned with SEO. * Here's how to make them work together. The stuff in this gist sets up a Twig filter (`obfuscate`) to create the obfuscated ids (for URLs), makes the obfuscator available as a service (`id_obfuscator`) so you can also generate obfuscated URLs in your controllers or whatever, and extends the DoctrineParamConverter to allow it to retrieve entities by their deobfuscated id. Following Phil Sturgeon's excellent advice in [Build APIs You Won't Hate](https://leanpub.com/build-apis-you-wont-hate), I've also added an option to allow multiple ids to be loaded at once, like `/resources/id1,id2,id3,id4`. It's really quite handy sometimes. Bewarned though; it won't 404 if only some of the ids are missing. Of this whole thing, this is the part that could do with the most attention, sorry! The good news is that it's totally optional, so if you want to avoid the potential shonkiness then just don't use it. In the example controller code I put separate actions to demonstrate how you use it with and without multiple-id support, but obviously don't use *both*, that's just silly. Pick one! If you don't like to read and just paste the code in, it'll crash. That's my petty vengeance at work :) I've used Zack Kitzmiller's [Tiny-php](https://github.com/zackkitzmiller/tiny-php) library here because it's simple and great, but you could use [hashids](http://hashids.org/php/) instead with very little change; same difference. Take it, use it (at your own risk), fix it, no need to credit me. I'm not sure it warrants clogging up Packagist with, but if you **do** decide to make it into a reusable Symfony bundle then I'd love to know about it. ## If you aren't using Symfony 2.6 (or you upgraded to it) * sf2.6 has an `app/config/services.yml` file, while if you started your project with an earlier version you probably don't. You can make your own and import it to `config.yml` or you could just put this stuff in there directly, whatever. * sf2.6 starts new projects with an AppBundle, following the Symfony Best Practices, while older versions don't (and actually make it kind of an arse to set one up, since it has no vendor namespace). Just… use whatever you're already using I guess. ## Suggested improvements * Read *APIs you won't hate* again to remember how to handle 404s with multiple ids * Support for different Tiny keys (e.g. for different entities) * Add tests * Make it a Bundle This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -2,23 +2,44 @@ namespace AppBundle\Controller; use AppBundle\Entity\Resource; use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; class ResourceController extends Controller { // … /** * @Route("/resources/{id}", name="resource_show") * @ParamConverter("resource", class="AppBundle:Resource", converter="obfuscated") */ public function showAction(Request $request, Resource $resource) { //… return $this->render('AppBundle:Resource:show.html.twig', [ 'resource' => $resource, ]); } /** * Alternative with support for multiple ids. Don't use both, pick one - * I've made this throw a fatal error so you don't just cut and paste :P * * @Route("/resources/{id}", name="resource_show") * @ParamConverter("resources", class="AppBundle:Resource", converter="obfuscated", options={ * "repository_method":"findById", * "multiple": true * }) */ public function showAction(Request $request, array $resources) { //… return $this->render('AppBundle:Resource:show.html.twig', [ 'resources' => $resources, ]); } } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -34,10 +34,17 @@ protected function getIdentifier(Request $request, $options, $name) { $id = parent::getIdentifier($request, $options, $name); if ($id && array_key_exists('multiple', $options) && $options['multiple']) { $id = array_map([$this->tiny, 'from'], array_filter(preg_split('/[\s,]+/', $id))); return $id; } if ($id) { return $this->tiny->from($id); } return false; } } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -2,6 +2,6 @@ {% block body %} //… <a href="{{ path('resource_show', { id: resource.id | obfuscate }) }}">Link to thing</a> // … {% endblock %} This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,3 @@ services: id_obfuscator: class: ZackKitzmiller\Tiny @@ -10,7 +9,7 @@ services: arguments: - "@doctrine" - "@id_obfuscator" tags: # Priority false means it won't ever run automatically; you have to ask for it - { name: request.param_converter, priority: false, converter: obfuscated } obfuscator_extension: -
mattattui renamed this gist
Oct 30, 2014 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
mattattui created this gist
Oct 30, 2014 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,24 @@ <?php namespace AppBundle\Controller; use AppBundle\Entity\Asset; use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; class AssetController extends Controller { // … /** * @Route("/resource/{id}", name="myroute") * @ParamConverter("asset", class="AppBundle:Asset", converter="obfuscated") */ public function showAction(Request $request, Asset $asset) { return $this->render('AppBundle:Asset:show.html.twig', [ 'asset' => $asset, ]); } } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,43 @@ <?php namespace AppBundle\Request\ParamConverter; use Doctrine\Common\Persistence\ManagerRegistry; use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\DoctrineParamConverter; use Symfony\Component\HttpFoundation\Request; use ZackKitzmiller\Tiny; /** * DoctrineParamConverter. * * @author Fabien Potencier <[email protected]> */ class ObfuscatedDoctrineParamConverter extends DoctrineParamConverter { /** * @var ManagerRegistry */ protected $registry; /** * @var ZackKitzmiller\Tiny */ protected $tiny; public function __construct(ManagerRegistry $registry = null, Tiny $tiny) { parent::__construct($registry); $this->tiny = $tiny; } protected function getIdentifier(Request $request, $options, $name) { $id = parent::getIdentifier($request, $options, $name); if ($id) { return $this->tiny->from($id); } return false; } } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,41 @@ <?php namespace AppBundle\Extension; use ZackKitzmiller\Tiny; class Obfuscator extends \Twig_Extension { private $tiny; public function __construct(Tiny $tiny) { $this->tiny = $tiny; } /** * Returns a list of functions to add to the existing list. * * @return array An array of functions */ public function getFilters() { return array( 'obfuscate' => new \Twig_Filter_Method($this, 'getObfuscatedId'), ); } public function getObfuscatedId($id) { return $this->tiny->to($id); } /** * Returns the name of the extension. * * @return string The extension name */ public function getName() { return 'obfuscate'; } } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,11 @@ # Using Tiny (ID obfuscator) with Symfony2's ParamConverters * Symfony's convenience methods for automatically fetching database entities from URL parameters are super-handy. * Obfuscated/hash IDs are a great idea. * Here's how to make them work together. The stuff in this gist sets up a Twig filter (`obfuscate`) to create the obfuscated ids (for URLs), makes the obfuscator available as a service (`id_obfuscator`) so you can also generate obfuscated URLs in your controllers or whatever, and extends the DoctrineParamConverter to allow it to retrieve entities by their deobfuscated id. I've used Zack Kitzmiller's [Tiny-php](https://github.com/zackkitzmiller/tiny-php) library here because it's simple and great, but you could use [hashids](http://hashids.org/php/) instead with very little change; same difference. Take it, use it (at your own risk), fix it, no need to credit me. I'm not sure it warrants clogging up Packagist with, but if you **do** decide to make it into a reusable Symfony bundle then I'd love to know about it. This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,22 @@ services: id_obfuscator: class: ZackKitzmiller\Tiny arguments: - "%id_obfuscator_key%" obfuscated_paramconverter: class: AppBundle\Request\ParamConverter\ObfuscatedDoctrineParamConverter arguments: - "@doctrine" - "@id_obfuscator" tags: - { name: request.param_converter, priority: false, converter: obfuscated } obfuscator_extension: private: true class: AppBundle\Extension\Obfuscator arguments: - "@id_obfuscator" tags: - { name: twig.extension } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,7 @@ {% extends '::layout.html.twig' %} {% block body %} //… <a href="{{ path('myroute', { id: asset.id | obfuscate }) }}">Link to thing</a> // … {% endblock %} This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,2 @@ parameters: id_obfuscator_key: "[generate this using vendor/zackkitzmiller/tiny/bin/genset]"