Sqids Bundle: Integrate Twig With Encode/Decode Filters

by Editorial Team 56 views
Iklan Headers

Hey guys! Today, we're diving deep into integrating Twig with encode/decode filters in the Sqids bundle. If you're coming from the hashids-bundle world, you'll find this quite familiar, but with a Sqids twist! Let's break down why this is awesome and how we're going to achieve it.

Description

The main goal here is to add a Twig extension that provides sqids_encode and sqids_decode filters. Think of it like this: you have an integer, and you want to turn it into a short, unique, and URL-friendly string (a sqid). Or, vice versa, you have a sqid, and you want to get back the original integer. This is super useful for creating clean and SEO-friendly URLs, obfuscating database IDs, and generally making your application more secure and user-friendly.

Why Sqids?

You might be wondering, "Why Sqids and not something else?" Well, Sqids is designed to be URL-friendly, using only lowercase alphanumeric characters. This makes it perfect for web applications. It also focuses on generating the shortest possible unique IDs, which is great for keeping your URLs clean and concise.

Use Cases

Imagine you're building an e-commerce platform. Instead of exposing your product IDs directly in the URL like example.com/product/12345, you can encode the ID using Sqids and have something like example.com/product/abcde. This not only looks better but also adds a layer of security by obfuscating the actual database ID.

Another use case is in generating unique referral codes. You can encode a user's ID to create a short, unique referral code that's easy to share and track.

Benefits of Twig Integration

Integrating Sqids with Twig means you can easily encode and decode IDs directly in your templates. This keeps your PHP code cleaner and more readable, as you don't have to pass pre-encoded or pre-decoded values to the template. It also makes your templates more expressive and easier to maintain.

Tasks

Okay, let's get down to the nitty-gritty. Here's what we need to do to make this happen:

1. Create src/Twig/SqidsExtension.php

First, we'll create a new class called SqidsExtension in the src/Twig/ directory. This class will be responsible for registering our sqids_encode and sqids_decode filters with Twig. The class needs to extend Twig\[Extension](https://twig.symfony.com/doc/3.x/advanced.html#creating-an-extension) and define the filters.

sqids_encode Filter

This filter will take an integer as input and return its Sqids-encoded representation. The implementation will use the Sqids library to perform the encoding.

<?php

namespace App\Twig;

use Sqids\Sqids;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;

class SqidsExtension extends AbstractExtension
{
 private $sqids;

 public function __construct(Sqids $sqids)
 {
 $this->sqids = $sqids;
 }

 public function getFilters(): array
 {
 return [
 new TwigFilter('sqids_encode', [$this, 'encode']),
 ];
 }

 public function encode(int $id): string
 {
 return $this->sqids->encode([$id]);
 }
}

sqids_decode Filter

Conversely, this filter will take a Sqids-encoded string as input and return the original integer. Again, we'll use the Sqids library for decoding.

<?php

namespace App\Twig;

use Sqids\Sqids;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;

class SqidsExtension extends AbstractExtension
{
 private $sqids;

 public function __construct(Sqids $sqids)
 {
 $this->sqids = $sqids;
 }

 public function getFilters(): array
 {
 return [
 new TwigFilter('sqids_decode', [$this, 'decode']),
 ];
 }

 public function decode(string $id): array
 {
 return $this->sqids->decode($id);
 }
}

2. Register the Twig Extension as a Service

Next, we need to register our SqidsExtension class as a service in Symfony's service container. This tells Symfony that our class is a service and that it should be managed by the container. We also need to tag the service with twig.extension to let Twig know that it's a Twig extension.

Here's how you can do it in config/services.yaml:

services:
 App\Twig\SqidsExtension:
 arguments: ['@Sqids\Sqids']
 tags:
 - { name: twig.extension }

This configuration tells Symfony to create an instance of SqidsExtension, inject the Sqids service as an argument, and register it as a Twig extension.

3. Add twig/twig as a Suggested Dependency

To ensure that users of our bundle have Twig installed, we'll add twig/twig as a suggested dependency in composer.json. This means that Composer will suggest installing Twig when our bundle is installed, but it won't be a hard requirement. This provides flexibility but also encourages users to have the necessary dependency.

{
 "suggest": {
 "twig/twig": "Required to use the Twig extension"
 }
}

4. Add Specs for the Twig Extension

Finally, we need to add specs (tests) for our Twig extension to ensure that it's working correctly. We'll create a new file called spec/Twig/SqidsExtensionSpec.php and write tests to verify that the sqids_encode and sqids_decode filters are encoding and decoding values as expected.

Here’s what a basic spec might look like using a testing framework like phpspec:

<?php

namespace spec\App\Twig;

use App\Twig\SqidsExtension;
use Sqids\Sqids;
use Twig\TwigFilter;
use PhpSpec\ObjectBehavior;

class SqidsExtensionSpec extends ObjectBehavior
{
 function let(Sqids $sqids)
 {
 $this->beConstructedWith($sqids);
 }

 function it_is_initializable()
 {
 $this->shouldHaveType(SqidsExtension::class);
 }

 function it_should_have_sqids_encode_filter(Sqids $sqids)
 {
 $this->getFilters()->shouldBeArray();
 $filters = $this->getFilters();
 $filters[0]->shouldBeAnInstanceOf(TwigFilter::class);
 $filters[0]->getName()->shouldBe('sqids_encode');
 $filters[0]->getCallable()->shouldBe([$this->getWrappedObject(), 'encode']);
 }

 function it_should_have_sqids_decode_filter(Sqids $sqids)
 {
 $this->getFilters()->shouldBeArray();
 $filters = $this->getFilters();
 $filters[0]->shouldBeAnInstanceOf(TwigFilter::class);
 $filters[0]->getName()->shouldBe('sqids_decode');
 $filters[0]->getCallable()->shouldBe([$this->getWrappedObject(), 'decode']);
 }

 function it_should_encode_id(Sqids $sqids)
 {
 $sqids->encode([1])->willReturn('jR');
 $this->encode(1)->shouldReturn('jR');
 }

 function it_should_decode_id(Sqids $sqids)
 {
 $sqids->decode('jR')->willReturn([1]);
 $this->decode('jR')->shouldReturn([1]);
 }
}

These specs ensure that our Twig extension is working as expected and that the sqids_encode and sqids_decode filters are correctly encoding and decoding values.

Reference: hashids-bundle Implementation

If you're familiar with the hashids-bundle, you can use its src/Twig/HashidsExtension.php as a reference. The implementation is quite similar, but you'll need to adapt it to use the Sqids library instead of Hashids. The core concepts of creating a Twig extension and registering filters remain the same. The key difference lies in the specific encoding and decoding logic.

Conclusion

And there you have it! We've successfully integrated Twig with encode/decode filters in the Sqids bundle. This makes it super easy to encode and decode IDs directly in your Twig templates, keeping your code clean, readable, and secure. Remember to follow the tasks outlined above, and don't hesitate to refer to the hashids-bundle implementation for guidance. Happy coding, and may your URLs be forever short and sweet!

By integrating Sqids with Twig, you are not only enhancing the functionality of your application but also improving its maintainability and security. Good job! Remember to keep your dependencies updated and your tests running to ensure that everything continues to work smoothly. This integration provides a seamless way to handle ID encoding and decoding within your Twig templates, making your development process more efficient and your application more robust. Always strive for clean, readable code and thorough testing to ensure the long-term success of your projects. The combination of Twig and Sqids offers a powerful toolset for any developer looking to create user-friendly and secure web applications. Keep exploring new ways to leverage these technologies to enhance your projects and stay ahead of the curve.