Reading list Switch to dark mode

    Create tabs in PrestaShop Symfony based module

    Updated 17 January 2022

    In this blog, we are going to learn how to create tabs in the PrestaShop back office through the module and manage its permission (ie. create, read, update and delete).

    In the PrestaShop back office, the links on the side menu are linked to ‘AdminControllers’ and ‘ModuleAdminController’ classes. Some links are created at the time of installation of the PrestaShop and some links are created through the module.

    Tabs registration

    In order to register a new link, add the below code in your main module class. PrestaShop will now use a property called ‘$tabs’, storing an array of link details. Each of them contains a class to add to the side menu.

    Define a tab in the menu

    $this->tabs = [
        [
            'route_name' => 'demo_tab_one',
            'class_name' => DemoTabOneController::TAB_CLASS_NAME,
            'visible' => true,
            'name' => $tabNames,
            'icon' => 'settings',
            'parent_class_name' => 'IMPROVE',
        ]
    ];

    Where:
    class_name: Class is called when the user will click on your link. This is the class name without the Controller part.
    route_name: Symfony route name, if your controller is Symfony-based (Since PrestaShop v1.7.7)
    name: Label displayed in the menu. If not provided, the class name is shown instead.
    parent_class_name: The parent menu, if you want to display it in a subcategory.
    icon: Icon name to use if any
    visible: Whether you want to display the tab or not. Hidden tabs are used when you don’t need a menu item but you still need to handle access rights.

    You can get more information about these parameters on the PrestaShop developer documentation.

    Searching for an experienced
    Prestashop Company ?
    Find out More

    We can also register the tabs manually at the time of module installation:

    private function manuallyInstallTab()
    {
        $tab = new Tab();
        $tab->active = 1;
        $tab->class_name = DemoTabTwoController::TAB_CLASS_NAME;
        // Only since 1.7.7, you can define a route name
        $tab->route_name = 'demo_tab_two';
        $tab->name = [];
        foreach (Language::getLanguages() as $lang) {
            $tab->name[$lang['id_lang']] = $this->trans('Demo tab two', [], 'Modules.Wkadmintabs.Admin', $lang['locale']);
        }
        $tab->icon = 'build';
        $tab->id_parent = (int) Tab::getIdFromClassName('IMPROVE');
        $tab->module = $this->name;
    
        return $tab->save();
    }

    So, let’s create a simple module “wkadmintabs”. Module file and folder structure will be like:

    +---config
    |      |- routes.yml
    |
    +---src
    |   \---controller
    |       \---Admin
    |             |-  DemoTabOneController.php
    |             |-  DemoTabTwoController.php
    |
    +---vendor (generated by composer.json)
    |
    \---views
    |   \---templates
    |        \---admin
    |               |- demotabone.html.twig
    |               |- demotabtwo.html.twig
    |
    |-  composer.json
    |-  wkadmintabs.php

    Add the main file ‘wkadmintabs.php’ of this module:

    <?php
    
    if (!defined('_PS_VERSION_')) {
        exit;
    }
    
    use Language;
    use PrestaShop\Module\Wkadmintabs\Controller\Admin\DemoTabOneController;
    use PrestaShop\Module\Wkadmintabs\Controller\Admin\DemoTabTwoController;
    
    require_once __DIR__ . '/vendor/autoload.php';
    
    class Wkadmintabs extends Module
    {
        public function __construct()
        {
            $this->name = 'wkadmintabs';
            $this->author = 'Webkul';
            $this->version = '1.0.0';
            $this->ps_versions_compliancy = ['min' => '1.7.7', 'max' => _PS_VERSION_];
    
            parent::__construct();
    
            $this->displayName = $this->l('Admin Controller Tabs');
            $this->description = $this->l('Create Tabs in Symfony Controller and manage its Permissions');
    
            // See https://devdocs.prestashop.com/1.7/modules/concepts/controllers/admin-controllers/tabs/
            $tabNames = [];
            foreach (Language::getLanguages(true) as $lang) {
                $tabNames[$lang['locale']] = $this->trans('Demo tab one', [], 'Modules.Wkadmintabs.Admin', $lang['locale']);
            }
            $this->tabs = [
                [
                    'route_name' => 'demo_tab_one',
                    'class_name' => DemoTabOneController::TAB_CLASS_NAME,
                    'visible' => true,
                    'name' => $tabNames,
                    'icon' => 'settings',
                    'parent_class_name' => 'IMPROVE',
                ]
            ];
        }
    
        public function install()
        {
            return parent::install() && $this->manuallyInstallTab();
        }
    
        /**
         * @return bool
         */
        private function manuallyInstallTab()
        {
            $tab = new Tab();
            $tab->active = 1;
            $tab->class_name = DemoTabTwoController::TAB_CLASS_NAME;
            // Only since 1.7.7, you can define a route name
            $tab->route_name = 'demo_tab_two';
            $tab->name = [];
            foreach (Language::getLanguages() as $lang) {
                $tab->name[$lang['id_lang']] = $this->trans('Demo tab two', [], 'Modules.Wkadmintabs.Admin', $lang['locale']);
            }
            $tab->icon = 'build';
            $tab->id_parent = (int) Tab::getIdFromClassName('IMPROVE');
            $tab->module = $this->name;
    
            return $tab->save();
        }
    }

    Create ‘DemoTabOneController.php’ and ‘DemoTabTwoController.php’ controller files under the “Controller\Admin” folder:

    <?php
    namespace PrestaShop\Module\Wkadmintabs\Controller\Admin;
    
    use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;
    use Symfony\Component\HttpFoundation\Response;
    
    class DemoTabOneController extends FrameworkBundleAdminController
    {
        const TAB_CLASS_NAME = 'WkAdminTabsControllerTabsOne';
    
        /**
         * @return Response
         */
        public function indexAction()
        {
            return $this->render('@Modules/wkadmintabs/views/templates/admin/demotabone.html.twig');
        }
    }
    <?php
    namespace PrestaShop\Module\Wkadmintabs\Controller\Admin;
    
    use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;
    use Symfony\Component\HttpFoundation\Response;
    
    class DemoTabTwoController extends FrameworkBundleAdminController
    {
        const TAB_CLASS_NAME = 'WkAdminTabsControllerTabsTwo';
    
        /**
         * @return Response
         */
        public function indexAction()
        {
            return $this->render('@Modules/wkadmintabs/views/templates/admin/demotabtwo.html.twig');
        }
    }

    Create ‘demotabone.html.twig’ and ‘demotabtwo.html.twig’ view files for both controllers under the “views/templates/admin” folder:

    {% extends "PrestaShopBundle:Admin:layout.html.twig" %}
    {% block content %}
        <h2>This is tab one content.</h2>
    {% endblock %}
    {% extends "PrestaShopBundle:Admin:layout.html.twig" %}
    {% block content %}
        <h2>This is tab two content.</h2>
    {% endblock %}

    Add ‘composer.json’ file and add the module information:

    {
        "description": "Create Tabs in Symfony Controller and manage its Permissions",
        "autoload": {
            "psr-4": {
                "PrestaShop\\Module\\Wkadmintabs\\":  "src/"
            }
        },
        "config": {
            "prepend-autoloader": false
        },
        "type": "prestashop-module"
    }

    Add ‘route.yml’ file to define the routes:

    demo_tab_one:
        path: wkadmin-tabs/demotabone
        methods: [GET]
        defaults:
            _controller: 'PrestaShop\Module\Wkadmintabs\Controller\Admin\DemoTabOneController::indexAction'
    
    demo_tab_two:
        path: wkadmin-tabs/demotabtwo
        methods: [GET]
        defaults:
            _controller: 'PrestaShop\Module\Wkadmintabs\Controller\Admin\DemoTabTwoController::indexAction'

    Once you install this module in the PrestaShop, two new menu links are available in the back office:

    Create tabs and manage permission admin side menu
    Admin Side Menu

    Tab permissions, accesses and roles

    At the time of the module installation, it automatically creates the appropriate roles in the ‘Tab::initAccess’ based on the class_name. For example, we are using ‘WkAdminTabsControllerTabsOne’ and ‘WkAdminTabsControllerTabsTwo’ as the class name then it will create the following roles in the PrestaShop:

    Create tabs and manage permission access control list
    Tab Permissions & Roles

    These roles will allow you to manage detailed permission in your controllers.

    We can provide access permission for every method used in the admin controller. Here is an example with a Symfony controller (WkAdminTabsControllerTabsOne).

    Nothing specific in this controller but notice the security annotation ‘@AdminSecurity’ that uses ‘request.get(‘_legacy_controller’)’ which will make the link between this controller and the routing configuration.

    <?php
    namespace PrestaShop\Module\Wkadmintabs\Controller\Admin;
    
    use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;
    <strong>use PrestaShopBundle\Security\Annotation\AdminSecurity;</strong>
    use Symfony\Component\HttpFoundation\Response;
    
    class DemoTabOneController extends FrameworkBundleAdminController
    {
        const TAB_CLASS_NAME = 'WkAdminTabsControllerTabsOne';
    
        /**
         * <strong>@AdminSecurity("is_granted('read', request.get('_legacy_controller'))")</strong>
         *
         * @return Response
         */
        public function indexAction()
        {
            return $this->render('@Modules/wkadmintabs/views/templates/admin/demotabone.html.twig');
        }
    }

    So, let’s update the ‘routes.yml’ file to add the ‘_legacy_controller’ parameter:

    demo_tab_one:
        path: wkadmin-tabs/demotabone
        methods: [GET]
        defaults:
            _controller: 'PrestaShop\Module\Wkadmintabs\Controller\Admin\DemoTabOneController::indexAction'
            # _legacy_controller is used to manage permissions
    <strong>        _legacy_controller: WkAdminTabsControllerTabsOne</strong>
    
    demo_tab_two:
        path: wkadmin-tabs/demotabtwo
        methods: [GET]
        defaults:
            _controller: 'PrestaShop\Module\Wkadmintabs\Controller\Admin\DemoTabTwoController::indexAction'
            # _legacy_controller is used to manage permissions
    <strong>        _legacy_controller: WkAdminTabsControllerTabsTwo</strong>

    You can also modify the error message and redirection link.

    @AdminSecurity("is_granted(['read'], request.get('_legacy_controller'))",
        message="You do not have permission to access this.",
        redirectRoute="some_route_name"
    )

    That’s all about this blog.

    If any issue or doubt please feel free to mention it in the comment section.

    I would be happy to help.

    Also, you can explore our PrestaShop Development Services & a large range of quality PrestaShop Modules.

    For any doubt contact us at [email protected].

    . . .

    Leave a Comment

    Your email address will not be published. Required fields are marked*


    Be the first to comment.

    Back to Top

    Message Sent!

    If you have more details or questions, you can reply to the received confirmation email.

    Back to Home