What if we define validations rules in the routing configuration 😱

Smaine Milianni
3 min readNov 20, 2021

💡 In this article, I’ll show how you can add validation on a Request content. (ℹ️ ️It’s more about a way to learn more about Request and event listener than a best practice)

A common use case when you create a route is to validate the Request content, suppose you expose an API that creates a User, you want to be sure that the name is not null, the email is valid and other stuff like this... There are many possibilities to do this, I’ll show another one 😉.

🍉 The idea is simple, the Symfony Routing allows us to specify extra information that will be then accessible from the famous Request object. We will use this possibility to pass our validation rules, then we will create a Listener that listens to the event Kernel.request and inside this listener, we will validate the request content with our validation rules 🔥

1- Create the Controller ⚒️

Suppose we expose an API that creates a user and we want to validate that the name is not blank and the email is a valid email.

We have to create a Route and inside the configuration, we add a custom array _validator inside the defaults option. We match each property with a Symfony constraint, in my example, I just have one constraint per property and I don’t add validator options like message… Feel free to change this to fit your needs. Then in the action if we get errors from the request attributes and if we have errors we format them to return a readable response.

🎁 (Bonus) I need an endpoint to list my users and I want to validate that the limit parameter is Positive.

Same stuff, I create my controller, add an extra parameter and match the property to validate with a constraint.

2- Create the Listener 🗜️

Our job is to listen to the kernel.request event, it allows us to get the Request content and the extra attributes before executing the logic inside a controller.

In the listener, we will create a collection of constraints and we will validate the submitted payload or the query string, it depends on the HTTP Method. Then we set the errors in the Request attributes to get them from the controller. 👌

3- Try it 😚

I make a POST request with a name = nulland a wrong email. I add a dump to output the errors:

$errors = $request->attributes->get('_errors');
dd($errors);

🎉As you can see, the validator did the job and validate the payload, now let’s try with a GET method. I make a GET with limit=-42

Same thing ✨, the validator did the job too.

4- Automation testing 🤖

But we are professional developers, so we have to write tests.

And it’s 💚

That’s all, thanks for reading 📚, I hope you liked it, don’t forget to clap 👏and share the article.

Follow me on Twitter or reach me on LinkedIn 👋

You can get the source code 👉 here

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Smaine Milianni
Smaine Milianni

Written by Smaine Milianni

Engineering Manager- Technical Lead - certified Symfony 7,6,5,4 and certified AWS Solution Architect - Remote Worker

Responses (3)

What are your thoughts?

i'm not convinced that this is the good and maintainable approach
magic properties (_validator, _errors) are passed arround leading to code that would be hard to follow and subsequently maintain; and piggybacking the router for extra context data…

I agree with my predecessors. It's a good way to play around with the framework, but the functionality itself isn't useful. The biggest issue for me is that there’s no possibility to inspect the code by phpStorm and static analysis tools like Psalm.

I agree with Marko here, this is lot of boring work and magic without autocompletion and event more work is to add custom constraints.
I have pet project (WIP) which is solving this with argument vaule resolver…