Generate a Symfony route from a module

Manual generation

If the module uses a symfony controller then the best way of route generation is described in symfony docs. However, module, especially if using legacy controllers, don’t always have access to the symfony container or router. The Link object offers some helpers to help generate urls related to Symfony controllers and routes.

Using router via Link::getUrlSmarty

<?php
use Link;

// Generate url with Symfony route
$symfonyUrl = Link::getUrlSmarty(array('entity' => 'sf', 'route' => 'admin_product_catalog'));

// Generate url with Symfony route and arguments
$symfonyUrl = Link::getUrlSmarty(array(
    'entity' => 'sf',
    'route' => 'admin_product_unit_action',
    'sf-params' => array(
        'action' => 'delete',
        'id' => 42,
    )
));
<?php
use Context;

$link = Context::getContext()->link;

// Generate url with Symfony route (first argument is the legacy controller, even though it should be ignored)
$symfonyUrl = $link->getAdminLink('AdminProducts', true, array('route' => 'admin_product_catalog'));

// Generate url with Symfony route and arguments
$symfonyUrl = $link->getAdminLink('AdminProducts', true, array(
    'route' => 'admin_product_unit_action',
    'action' => 'delete',
    'id' => 42,
));

Not every developer use the getAdminLink method the same way, therefore the _legacy_link is able to recognize different uses of this method, for example via an action parameter (e.g: ?controller=AdminEmails&action=export).

But sometimes urls simply insert the action name as a parameter (e.g: ?controller=AdminPaymentPreferences&update). As long as the actions have been migrated and correctly set up they will be successfully converted.

Given this configuration:

admin_payment_preferences:
    path: /preferences
    methods: [GET]
    defaults:
        _controller: PrestaShopBundle:Admin\Improve\Payment\PaymentPreferences:index
        _legacy_controller: AdminPaymentPreferences
        _legacy_link: AdminPaymentPreferences

admin_payment_preferences_process:
    path: /preferences/update
    methods: [POST]
    defaults:
        _controller: PrestaShopBundle:Admin\Improve\Payment\PaymentPreferences:processForm
        _legacy_controller: AdminPaymentPreferences
        _legacy_link: AdminPaymentPreferences:update
<?php
    $link = New Link();

    //These calls will return /preferences
    $link->getAdminLink('AdminPaymentPreferences'); 
    $link->getAdminLink('AdminPaymentPreferences', true, ['action' => 'list']);
    $link->getAdminLink('AdminPaymentPreferences', true, [], ['action' => 'index']);

    //These calls will return /preferences/update
    $link->getAdminLink('AdminPaymentPreferences', true, [], ['action' => 'update']);
    $link->getAdminLink('AdminPaymentPreferences', true, [], ['update' => true]); =>
    $link->getAdminLink('AdminPaymentPreferences', true, [], ['update' => '']); =>
    
    //This call will return ?controller=AdminPaymentPreferences&action=export
    //because the export action has not been migrated yet
    $link->getAdminLink('AdminPaymentPreferences', true, [], ['action' => 'export']);

Be careful, Link is sometimes misused

Some examples have been found where urls are generated by a mix of getAdminLink and concatenating parameters:

<?php
    $link = new Link();
    $link->getAdminLink('AdminPaymentPreferences') . '?action=update';

This won’t work because the parameters will be appended to the index url. You should be extra careful about these misused code and replace it according to the minimum PrestaShop version you are targeting:

  • If the controller has already been migrated in your minimum supported version, use the Router service directly with the appropriate route name and parameters.
  • If the controller hasn’t been migrated as of your minimum supported version:
    • For >= 1.7.5, use getAdminLink method with the parameters fully injected in the function.
    • For < 1.7.5, consider creating your own Link class adapter to switch to the appropriate routing mode for each PrestaShop version (see example).

Remember that _legacy_link is only available since 1.7.5 version of PrestaShop, for older versions you need to update the Link class to manage routing conversion.

<?php
    // classes/Link.php, in getAdminLink()
    $routes = array(
        'AdminModulesSf' => 'admin_module_manage',
        'AdminStockManagement' => 'admin_stock_overview',
        //...
        'LegacyController' => 'migrated_route',
    );

This will only work for one route/one controller the association by action does not work before 1.7.5.

Javascript routes

In order to generate a symfony route in javascript, you can use the Router component.

You can use it like this:

import Router from '@components/router';

this.router = new Router();
const route = this.router.generate('my_route', {parameters});

It however uses a computed file that you might need to recompute if you modified some route settings.

You can recompute it using this:

php bin/console fos:js-routing:dump --format=json

And put it in admin-dev/themes/new-theme/js/fos_js_routes.json

It is important that route is exposed (has the option exposed: true in route configuration), else javascript router will not be able to reach it.