Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

A back office page: ModuleAdminController

Reviews pile up in the table, and the shop owner needs to see and delete them. The shortest way to a list page in the back office is the legacy ModuleAdminController. It belongs to the legacy core but does a lot by itself: from a description of columns it builds a table with sorting, filters and pagination.

Where the controller lives

Back office controllers are kept in the controllers/admin folder. Create the file by hand:

modules/acmehello/
├── acmehello.php
├── classes/
│   └── AcmeReview.php
├── controllers/
│   ├── admin/
│   │   └── AdminAcmehelloReviewsController.php
│   └── front/
│       └── reviews.php
├── upgrade/
└── views/

The controller

<?php
// modules/acmehello/controllers/admin/AdminAcmehelloReviewsController.php
class AdminAcmehelloReviewsController extends ModuleAdminController
{
    public function __construct()
    {
        $this->bootstrap = true;
        $this->table = 'acmehello_review';
        $this->className = 'AcmeReview';
        $this->identifier = 'id_review';
 
        parent::__construct();
 
        $this->fields_list = [
            'id_review' => ['title' => 'ID', 'class' => 'fixed-width-xs'],
            'author' => ['title' => $this->trans('Author', [], 'Modules.Acmehello.Admin')],
            'rating' => ['title' => $this->trans('Rating', [], 'Modules.Acmehello.Admin')],
        ];
    }
}

The class name starts with Admin and ends with Controller, and the file name matches the class name. The properties say which table and which model to work with, and fields_list lists the columns.

Registering the page

The back office opens a controller only if it is registered as a tab — a menu item. Tabs are described in the constructor of the main class, before parent::__construct():

// modules/acmehello/acmehello.php
$this->tabs = [
    [
        'name' => 'Reviews',
        'class_name' => 'AdminAcmehelloReviews',
        'parent_class_name' => 'AdminCatalog',
        'visible' => true,
    ],
];

class_name is the controller class name without the Controller ending. Tabs are created when the module is installed, so it has to be reset:

php bin/console prestashop:module reset acmehello

A "Reviews" item appears in the "Catalog" section of the back office menu. Open it: the page shows a table with the id, author and rating of every review. Tabs are covered in detail in the next lesson.

Columns

Column keyWhat it sets
titleThe heading
typeThe value type: datetime, bool, price
classThe CSS class of the cell, for example fixed-width-xs
searchfalse removes the filter for the column
orderbyfalse forbids sorting

Add a date column and a default sort order:

// in the constructor, after parent::__construct()
$this->fields_list['date_add'] = [
    'title' => $this->trans('Date', [], 'Admin.Global'),
    'type' => 'datetime',
];
 
$this->_defaultOrderBy = 'date_add';
$this->_defaultOrderWay = 'DESC';

The list gets a date column, and new reviews move to the top.

Row actions

// in the constructor, after parent::__construct()
$this->addRowAction('delete');
 
$this->bulk_actions = [
    'delete' => [
        'text' => $this->trans('Delete selected', [], 'Admin.Actions'),
        'confirm' => $this->trans('Delete selected items?', [], 'Admin.Notifications.Warning'),
    ],
];

Every row gets a "Delete" button, and a menu of actions for checked rows appears under the table. The controller performs the deletion itself through the AcmeReview model.

The edit form

The edit action is added the same way: $this->addRowAction('edit'). Its form is described in the renderForm() method with the $this->fields_form array — in the same format as HelperForm from the settings lesson. The controller takes care of saving too.

When to choose this way

WayWhen it fits
ModuleAdminControllerA simple list and form over your own table, needed fast
A Symfony controllerA page with its own markup and logic; the main direction of the platform

Legacy controllers work in PrestaShop 8 and 9, but new pages of the back office itself are written on Symfony. That way is covered in the lesson "A back office page on Symfony".

Common mistake

The controller is created, but the back office answers "Page not found" for its link. The reason is that the controller is not registered as a tab: the tabs entry was added but the module was not reset, or class_name kept the Controller ending. Check the name and run prestashop:module reset.

Thanks for reading!

Donate to the site — we work hard for you.