Notice: You are browsing the documentation for PrestaShop 9, which is currently in development.
You might want to read the documentation for the current version, PrestaShop 8. Read the current version of this page
Using modern pages, you will have access to the PrestaShop debug toolbar, the service container, Twig and Doctrine, among others. For your views, the PrestaShop UI Kit is available, built on top of Bootstrap 4 and ensuring your views are consistent with the PrestaShop Back Office.
Somewhere in your module declare a new class that will act as a Controller:
<?php
// modules/your-module/src/Controller/DemoController.php
namespace MyModule\Controller;
use Doctrine\Common\Cache\CacheProvider;
use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;
class DemoController extends FrameworkBundleAdminController
{
private $cache;
// you can use symfony DI to inject services
public function __construct(CacheProvider $cache)
{
$this->cache = $cache;
}
public function demoAction()
{
return $this->render('@Modules/your-module/templates/admin/demo.html.twig');
}
}
If you want Symfony Dependency Injection to inject services into your controller, you need to use specific YAML service declaration:
services:
# The name of the service must match the full namespace class
MyModule\Controller\DemoController:
class: MyModule\Controller\DemoController
arguments:
- '@doctrine.cache.provider'
You can also retrieve services with the container available in symfony controllers ->
<?php
// modules/your-module/src/Controller/DemoController.php
namespace MyModule\Controller;
use Doctrine\Common\Cache\CacheProvider;
use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;
class DemoController extends FrameworkBundleAdminController
{
public function demoAction()
{
// you can also retrieve services directly from the container
$cache = $this->container->get('doctrine.cache');
return $this->render('@Modules/your-module/templates/admin/demo.html.twig');
}
}
You have access to the Container, to Twig as rendering engine, the Doctrine ORM, everything from Symfony framework ecosystem.
Note that you must return a Response
object, but this can be a JsonResponse
if you plan to make a single page application (or “SPA”).
You must enable the autoloading for this Controller. For example using a composer.json
file for your module.
Use namespace for your Controller file
<?php
// modules/your-module/src/Controller/DemoController.php
namespace MyModule\Controller;
use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;
Configure composer to autoload this namespace
{
"name": "you/your-module",
"description": "...",
"autoload": {
"psr-4": {
"MyModule\\Controller\\": "src/Controller/"
}
},
"config": {
"prepend-autoloader": false
},
"type": "prestashop-module"
}
You should run composer dumpautoload
console command from where your module’s composer.json file is located.
If you do not have “composer” you can search for it. Composer is available on any operating system.
Now we have created and loaded your controller, you need to declare a route. A route map an action of your controller to an URI.
This is really simple (and very well documented in Symfony’s Routing component documentation):
For instance:
# modules/your-module/config/routes.yml
your_route_name:
path: your-module/demo
methods: [GET]
defaults:
_controller: 'MyModule\Controller\DemoController::demoAction'
_controller
attribute, you don’t even need to create your own controller! You could even use a public function from your module main class. Even so, we strongly suggest using a controller.::
) and not the single colon (:
)
to separate classes and method names!
Since Symfony 4.1 the bundle notation is going to be deprecated: https://symfony.com/blog/new-in-symfony-4-1-deprecated-the-bundle-notationThe Controller in the previous example will now be available if you browse /admin-dev/modules/your-module/demo
. Pay attention to this path: it starts with /modules
.
This is because all module routes are, by default, prefixed with /modules
.
If however you need or wish your route not to be prefixed, you can use the _disable_module_prefix
route option to disable the prefix.
# modules/your-module/config/routes.yml
your_route_name:
path: your-module/demo
methods: [GET]
defaults:
_controller: 'MyModule\Controller\DemoController::demoAction'
_disable_module_prefix: true
Valid URIs required a security token.
In order to generate the valid URI of a controller you created from inside the main module class, you need to get the Symfony router. The router will build the URI using generate
with the route name, as in the below example.
<?php
# modules/my-module/my-module.php
use PrestaShop\PrestaShop\Adapter\SymfonyContainer;
class MyModule extends Module
{
protected function generateControllerURI()
{
$router = SymfonyContainer::getInstance()->get('router');
return $router->generate('my_route_name');
}
}
It is safer to define permissions required to use your controller, this can be configured using the #[AdminSecurity]
attribute and some configuration in your routing file. You can read this documentation if you need more details about Controller Security.