The settings page
For the shop owner to change module settings from the back office, the module needs a settings page. No separate file is required: it is enough to add a getContent() method to the main class. Whatever it returns, the back office shows as the module page.
The getContent method
// modules/acmehello/acmehello.php
public function getContent(): string
{
return '<p>Settings will be here.</p>';
}Open "Modules → Module Manager" and find the module: it now has a "Configure" button. Clicking it opens a page with this line. There is no need to reset the module.
The form
A form is not built by hand: it is described with an array, and the HelperForm class draws the fields in the back office style. Put this into a separate method:
// modules/acmehello/acmehello.php
private function renderForm(): string
{
$form = [
'form' => [
'legend' => ['title' => $this->trans('Settings', [], 'Admin.Global')],
'input' => [
[
'type' => 'text',
'label' => $this->trans('Greeting text', [], 'Modules.Acmehello.Admin'),
'name' => 'ACMEHELLO_GREETING',
'required' => true,
],
],
'submit' => ['title' => $this->trans('Save', [], 'Admin.Actions')],
],
];
$helper = new HelperForm();
$helper->module = $this;
$helper->name_controller = $this->name;
$helper->token = Tools::getAdminTokenLite('AdminModules');
$helper->currentIndex = AdminController::$currentIndex . '&configure=' . $this->name;
$helper->submit_action = 'submitAcmehello';
$helper->default_form_language = (int) Configuration::get('PS_LANG_DEFAULT');
$helper->fields_value = [
'ACMEHELLO_GREETING' => Configuration::get('ACMEHELLO_GREETING'),
];
return $helper->generateForm([$form]);
}
public function getContent(): string
{
return $this->renderForm();
}The settings page now shows a "Settings" block with one field that already holds the current text, and a "Save" button. The button does not save anything yet.
What is set on the helper
| Property | What for |
|---|---|
module | The module the form belongs to |
token | The back office security key: without it the submit is rejected |
currentIndex | The address the form is sent to — this same settings page |
submit_action | The name of the submit button. It tells that the form was sent |
fields_value | Current field values: the key is the field name |
Saving
The form is sent to the same page, so getContent() first checks whether data has arrived:
// modules/acmehello/acmehello.php
public function getContent(): string
{
$output = '';
if (Tools::isSubmit('submitAcmehello')) {
$greeting = trim((string) Tools::getValue('ACMEHELLO_GREETING'));
if ($greeting === '' || !Validate::isGenericName($greeting)) {
$output .= $this->displayError(
$this->trans('Enter the greeting text.', [], 'Modules.Acmehello.Admin')
);
} else {
Configuration::updateValue('ACMEHELLO_GREETING', $greeting);
$output .= $this->displayConfirmation(
$this->trans('Settings saved.', [], 'Modules.Acmehello.Admin')
);
}
}
return $output . $this->renderForm();
}Change the text and press "Save": a green message appears above the form, and the storefront home page shows the new greeting. If you clear the field, a red error is shown and the value stays the same.
What is used here
| Call | What it does |
|---|---|
Tools::isSubmit('submitAcmehello') | Checks that the request contains a button with this name |
Tools::getValue('ACMEHELLO_GREETING') | Reads a field from the request |
Validate::isGenericName() | Checks that the string has no dangerous characters |
displayError() | Returns the HTML of a red message |
displayConfirmation() | Returns the HTML of a green message |
Common mistake
The name in submit_action and the name in Tools::isSubmit() differ — for example submitAcmehello and submitAcmeHello. The form is sent, the page reloads, but nothing is saved and there are no messages. These two strings must match exactly, including letter case.