Symfony ParamConverter is a very powerful feature provided by the Symfony framework that allows you to automatically convert route parameters into objects or other data types.Typically is declared as an Event Listener and is triggered in each incoming HTTP Request.

symfony param converter

 

Examples of how you can use Symfony ParamConverter:

Entity Conversion:
Suppose you have an entity called Product with an identifier productId. You can use ParamConverter to automatically fetch the Product object from the database based on the productId passed in the route parameter.

use App\Entity\Product;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;

/**
 * @Route("/product/{productId}")
 * @ParamConverter("product", class="App\Entity\Product")
 */
public function showProduct(Product $product)
{
    // $product will contain the Product object based on the productId
    // ...
}

In this example, Symfony ParamConverter simplifies the process of fetching an entity object based on a route parameter. The @ParamConverter annotation is used to specify the conversion. The class option specifies the target entity class to which the parameter should be converted.

Additionally, you can customize the query used to retrieve the entity by adding additional options. For example, you can specify a different database column to match the route parameter by using the options option:

/**
 * @Route("/product/{slug}")
 * @ParamConverter("product", class="App\Entity\Product", options={"mapping": {"slug": "name"}})
 */
public function showProduct(Product $product)
{
    // The 'slug' route parameter will be used to fetch the Product object by the 'name' column
    // ...
}

 

 

Type Conversion:
ParamConverter can also be used to convert route parameters into specific data types other than entities. For example, let's say you have a route parameter date that represents a date string, and you want to convert it into a DateTime object.

use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use DateTime;

/**
 * @Route("/event/{date}")
 * @ParamConverter("eventDate", converter="datetime", options={"format": "Y-m-d"})
 */
public function showEvent(DateTime $eventDate)
{
    // $eventDate will contain the DateTime object based on the date parameter
    // ...
}

In this example, the @ParamConverter annotation uses the converter option to specify the built-in datetime converter.

The options option allows you to provide additional configuration for the converter. In this case, the format option is used to specify the expected format of the date string in the route parameter. The datetime converter will then parse the parameter value and convert it into a DateTime object automatically.

You can use various other built-in converters provided by Symfony, such as bool, int, float, etc., to convert route parameters into different data types.

 

Custom Converter:
You can also create your own custom ParamConverter to perform a specific conversion logic. For example, let's say you want to convert a route parameter userId into a User object by fetching it from a custom service.

use App\Service\UserService;
use App\Entity\User;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;

/**
 * @Route("/user/{userId}")
 * @ParamConverter("user", converter="app.user_converter")
 */
public function showUser(User $user)
{
    // $user will contain the User object based on the userId
    // ...
}

In your custom converter app.user_converter, you can define the conversion logic using the ParamConverterInterface.

use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface;
use Symfony\Component\HttpFoundation\Request;
use App\Service\UserService;
use App\Entity\User;

class UserConverter implements ParamConverterInterface
{
    private $userService;

    public function __construct(UserService $userService)
    {
        $this->userService = $userService;
    }

    public function apply(Request $request, ParamConverter $configuration)
    {
        $userId = $request->attributes->get('userId');
        $user = $this->userService->getUserById($userId);

        $request->attributes->set($configuration->getName(), $user);
        return true;
    }

    public function supports(ParamConverter $configuration)
    {
        return $configuration->getName() === 'user';
    }
}

 

In my case, I use a custom ParamConverter set as an event listener, to convert DTOs in all Api Endpoints. For more on this go to my Article: Using DTOs in PHP Symfony

Thanks to this powerful feature, I can save tons of hours of development. Definitely, this ParamConverter is one of my favorite features in Symfony Framework.