These class are accessible from the front-office and add features to the customers.
In order to have a front controller read by PrestaShop, these 3 rules have to be followed:
controllers/front/
of the module.<ModuleClassName><FileName>ModuleFrontController
.ModuleFrontController
.Let’s say we want a controller responsible of payments validation in our
module cheque
.
We create a file /modules/cheque/controllers/front/validation.php
and its class:
<?php
/**
* <ModuleClassName> => Cheque
* <FileName> => validation.php
* Format expected: <ModuleClassName><FileName>ModuleFrontController
*/
class ChequeValidationModuleFrontController extends ModuleFrontController
{
}
That’s all, methods added to the class will be taken in account by PrestaShop automatically.
The controllers added in a module extend ModuleFrontController
, itself extending FrontController
& Controller
.
They provide access to the environment in which they run.
$this->module
is the instance of the module responsible of the controller.$this->context
delivers the result of Context::getContext()
.Other existing properties may be useful and can be discovered by looking at the parent classes content (by following links above) or with dump($this)
.
There are basically two kinds of HTTP calls possible for a controller:
For an advanced use, others HTTP methods can also be called ( such as PUT, PATCH, DELETE ).
Depending of the request made to the controller, a different method will be called by the core.
Handling requests can be done by implementing the method initContent()
in
the front controller. Note the parent class also implements it, do not forget
to call it as well.
Its purpose should be assigning the variables to smarty, and setting the template to be displayed.
The smarty engine is available in the context
property of the controller.
Assigning variables can be done with its method assign(array $vars)
.
<?php
public function initContent()
{
// In the template, we need the vars paymentId & paymentStatus to be defined
$this->context->smarty->assign(
array(
'paymentId' => Tools::getValue('id'), // Retrieved from GET vars
'paymentStatus' => [...],
));
}
This is the second part we expect in the method initContent()
.
HTML content should be stored in a smarty template, available in
the module subfolder views/templates/front/
.
The method setTemplate(...)
expect the template file name as parameter. There is no
need to write its complete path, as PrestaShop expects to find it in the folder
views/templates/front/
of the same module.
<?php
public function initContent()
{
// In the template, we need the vars paymentId & paymentStatus to be defined
$this->context->smarty->assign(
array(
'paymentId' => Tools::getValue('id'), // Retrieved from GET vars
'paymentStatus' => [...],
));
// Will use the file modules/cheque/views/templates/front/validation.tpl
$this->setTemplate('module:cheque/views/templates/front/validation.tpl');
}
POST requests will be managed from the method postProcess()
.
It does not receive parameters and does not expect any value to be returned,
but user input can be checked with Tools::getIsset(...)
and retrieved with
Tools::getValue(...)
.
When done, controllers generally redirects to another route, by using
Tools::redirect(<url>)
.
Addresses to your controller can be generated easily with the class Link
:
<?php
public function Link::getModuleLink($module, $controller, array $params = array());
$module
is the technical name of the module, $controller
is the controller
file name (without ‘.php’), and $params
is an array of variables to add in a
customized route or simply as GET params.
The generated address handles automatically HTTP or HTTPS environments, with or without URL rewriting.
<?php
Context::getContext()->link->getModuleLink('cheque', 'validation', array('idPayment' => 1337));
http://<shop_domain>/index.php?idPayment=1337&fc=module&module=cheque&controller=validation&id_lang=1
http://<shop_domain>/en/module/cheque/validation?idPayment=1337
When you call controller via AJAX, you need to add ajax
parameter in the url.
Context::getContext()->link->getModuleLink('cheque', 'validation', array('idPayment' => 1337, 'ajax'=>true));
http://<shop_domain>/index.php?idPayment=1337&fc=module&module=cheque&controller=validation&id_lang=1&ajax=true
http://<shop_domain>/en/module/cheque/validation?idPayment=1337&ajax=true
Set the property $auth
to true
if you want guests to be redirected to the
login page automatically.
<?php
public $auth = true;
public $guestAllowed = false;
You can force the maintenance page to be displayed when a customer reaches a controller.
<?php
protected $maintenance = true;
When SSL is enabled to a shop, you can force a call to a controller to be secured by redirecting it to HTTPS.
<?php
public $ssl = true;
Thanks to Symfony, modules may implement Console commands for cron tasks.
For modules compatible with early versions of PrestaShop 1.7 and previous major versions, there is no dedicated handler for CLI calls. A workaround is available with front controllers containing specific checks for CLI calls.
Implementing a controller instead of a simple PHP script will allow you to avoid some issues such as a non-instanciated Context or Symfony Kernel, especially on the latest versions of PrestaShop (i.e display of prices from PS 1.7.6). That’s why, even for CLI calls triggered by a cron jobs, we recommend having a controller. The trick is to define it as an Ajax call to prevent the page template to be displayed.
The following code provides a base for a cron task in the module examplemodule
.
modules/examplemodule/controllers/front/cron.php
<?php
class ExampleModuleCronModuleFrontController extends ModuleFrontController
{
/** @var bool If set to true, will be redirected to authentication page */
public $auth = false;
/** @var bool */
public $ajax;
public function display()
{
$this->ajax = 1;
if (!Tools::isPHPCLI()) {
$this->ajaxRender('Forbidden call.');
}
// Additional token checks
// ...
$this->ajaxRender("hello\n");
}
}
This controller can now be triggered by creating a PHP file that initiates the route to the controller, then includes the index.php at the root of PrestaShop in order to init the dispatcher and your controller.
This kind of script is also useful if a standalone PHP script interacting with PrestaShop has been migrated to a ModuleFrontController. The URLs to call would change by moving into a Controller, but the old one would be still accessible with this workaround.
modules/examplemodule/cron.php
<?php
$_GET['fc'] = 'module';
$_GET['module'] = 'examplemodule';
$_GET['controller'] = 'cron';
require_once dirname(__FILE__) . '/../../index.php';
The code is now callable via the php command on a terminal:
$ php modules/examplemodule/cron.php
hello