Ludovic Frank - Freelance developer

Modifying a slug in Symfony? Yes ... but cleanly

ionicons-v5-k Ludovic Frank May 24, 2021
91 reads Level:

This week's article is all about developers, yes ... there's something for everyone.
How are you? Whit Monday and all that ... yeah well, that's no reason to get up and get to work.

What's a slug?

For the guys at the back, we'll remind you what a slug is. It's a "string" normalized so that it can be inserted into a URL, for example on the article you're reading in your address bar there's no "index.php?article=49" because well .... it's ugly (if it's ugly, that's all.), a nice URL that lets you know just by looking at it what you're talking about ... that's better! Take a look at the address bar on this page: just by reading it, you'll know you're on a blog, and that you're about to read an article about slug and symfo ... that's it!

The slug problem

On this blog, the slug is generated from the title of the article, so if I change the title of my article, I create a dead link, a link that has already been shared... so people clicking on the link will get a nice "404, page not found" (yes, my 404 page is nice, but that's no reason ...)
Personally, I don't have the problem because I know how it works and I avoid changing my titles. If I need to, I do a "301 redirect" in the configuration of my web server (NGINX, for the curious).
But I've had the same problem several times for client projects: they made a mistake in the title, so I have to change it, and modifying the web server config each time is a bad idea, and it's forbidden to make dead links, so what do you do?

Store old slugs in a table

This is the solution I chose, I could have done it with a separate table and made a relationship, but I don't like this idea, why you may ask? Because it's a lot of extra tables (it's not just blog posts that use a slug).

The prerequisites for our case are :
- A MariaDB 10.3 server at least (earlier versions don't support JSON tables)

- The "scienta/doctrine-json-function" extension for Doctrine, so that you can make a DQL query that fetches (compose install all that stuff)

Entity modification

Do you have all the prerequisites? Well ... let's get started! (and if you don't ... what are you waiting for??)
We're already going to modify our entity containing our slug by adding an attribute to it (I call it oldSlug) and by adding a slug to our array each time the title changes (in my case, this is what my slug is based on).

Very simple, isn't it? Here we have an array containing all the old slugs

DQL query to find an article based on one of these old slugs

Now we'll add a method to our repository.

Modifying the controller

Now we need to do a 301 redirect. If we can't find our basic article and we find it via an old slug, we can't directly redirect the page for two reasons:

  • Duplicate content, which is very, very bad (SEO fans will understand).
  • The query we've added to the repository doesn't take into account other parameters (activated article? publication date? ...).


So there you have it: you can modify your slugs without breaking the links, which comes in handy in some cases to keep the tree structure clean.
See you next week?