В административной панели PrestaShop ссылки в боковом меню связаны с классами AdminControllers и ModuleAdminController. Первые приходят из ядра PrestaShop, но вторые определяются модулями. Если вы хотите добавить ссылку на ваш ModuleAdminController в боковую панель административной панели, этот гид для вас.
Регистрация вкладок
Для регистрации новых ссылок откройте основной класс вашего модуля.
Мы будем использовать свойство $tabs
, которое хранит массив деталей ссылки. Каждая из них содержит класс (= ссылку) для добавления в боковое меню.
Как определить вкладку в меню
В зависимости от предоставленных опций, ваши ссылки не будут отображаться одинаково:
Свойство | Обязательно | Тип | Описание | Пример |
---|---|---|---|---|
class_name | Да | Строка |
Класс, который будет вызван при клике на вашу ссылку. Это имя класса без части Controller .
|
"AdminGamification" |
route_name | Нет | Строка | Имя маршрута Symfony, если ваш контроллер основан на Symfony. | "gamification_configuration" |
name | Нет | Строка | Строка[] | Метка, отображаемая в меню. Если не указана, вместо нее будет показано имя класса. | "Merchant Expertise" |
parent_class_name | Нет | Строка | Родительское меню, если вы хотите отобразить его в подкатегории. См. ниже доступные значения. | |
icon | Нет | Строка | Имя иконки, если есть. | "shopping_basket" |
visible | Нет | Булево | Хотите ли вы отображать вкладку или нет. Скрытые вкладки используются, когда вам не нужен элемент меню, но нужно управлять правами доступа. | true |
wording | Нет | Строка | Ключ перевода для перевода метки меню. | "Merchant Expertise" |
wording_domain | Нет | Строка | Домен перевода для перевода метки меню. | "Modules.Gamification.Admin" |
Как указать метку меню
По умолчанию ваша вкладка будет отображаться в меню с именем класса. Если вы хотите использовать другую метку, вы можете установить свойство name
. Эта метка может быть переведена двумя способами.
Вариант 1: Использовать одну метку для всех языков
Если вы хотите добавить одно имя для всех доступных и активных языков на сайте, просто установите ключ name
с одной строкой:
<?php
class mymodule extends Module
{
public $tabs = [
[
'name' => 'Merchant Expertise', // Одно имя для всех языков
'class_name' => 'AdminGamification',
'visible' => true,
'parent_class_name' => 'ShopParameters',
],
];
// ...
}
Вариант 2: Использовать разные имена для каждого языка
С PrestaShop 1.7.8
Начиная с версии 1.7.8 вы можете объявить wording
и wording_domain
, чтобы использовать систему перевода. Это позволит меню переводиться автоматически, используя либо предоставленные каталоги переводов, либо интерфейс перевода.
<?php
class mymodule extends Module
{
public $tabs = [
[
'name' => 'Merchant Expertise', // Значение по умолчанию, если перевод недоступен
'class_name' => 'AdminGamification',
'parent_class_name' => 'ShopParameters',
'wording' => 'Merchant Expertise', // Ключ перевода
'wording_domain' => 'Modules.Gamification.Admin', // Домен перевода
],
];
// ...
}
Альтернатива - объявить свои переводы
В предыдущих версиях PrestaShop wording
и wording_domain
будут проигнорированы. В этом случае вам нужно будет предоставить переводы для каждого языка заранее.
Вы можете добавить свои переводы по локали (например, fr-FR
) или по языку (например, fr
) - оба варианта допустимы.
<?php
class mymodule extends Module
{
public $tabs = [
[
'name' => [
'en' => 'Merchant Expertise', // Значение по умолчанию
'fr' => 'Expertise PrestaShop',
...
],
'class_name' => 'AdminGamification',
'parent_class_name' => 'ShopParameters',
'wording' => 'Merchant Expertise', // Игнорируется в версиях PS < 1.7.8
'wording_domain' => 'Modules.Gamification.Admin', // Игнорируется в версиях PS < 1.7.8
],
];
// ...
}
Важно упорядочение. Если язык пользователя не найден в ваших переведенных именах, будет использовано первое значение в массиве в качестве значения по умолчанию. Поэтому мы советуем вам сначала определить значение на английском языке.
Какой родительский элемент выбрать?
Вот текущая структура бокового меню PrestaShop на момент написания этой страницы. Вы можете выбрать элемент из этого списка, чтобы использовать его в качестве родителя.
- AdminDashboard
- SELL
- AdminParentOrders
- AdminOrders
- AdminInvoices
- AdminSlip
- AdminDeliverySlip
- AdminCarts
- AdminCatalog
- AdminProducts
- AdminCategories
- AdminTracking
- AdminParentAttributesGroups
- AdminParentManufacturers
- AdminAttachments
- AdminParentCartRules
- AdminParentCustomer
- AdminCustomers
- AdminAddresses
- AdminOutstanding
- AdminParentCustomerThreads
- AdminCustomerThreads
- AdminOrderMessage
- AdminReturn
- AdminStats
- AdminStock
- AdminWarehouses
- AdminParentStockManagement
- AdminSupplyOrders
- AdminStockConfiguration
- AdminParentOrders
- IMPROVE
- AdminParentModulesSf
- AdminModulesSf
- AdminModules
- AdminAddonsCatalog
- AdminParentThemes
- AdminThemes
- AdminThemesCatalog
- AdminCmsContent
- AdminModulesPositions
- AdminImages
- AdminParentShipping
- AdminCarriers
- AdminShipping
- AdminParentPayment
- AdminPayment
- AdminPaymentPreferences
- AdminInternational
- AdminParentLocalization
- AdminParentCountries
- AdminParentTaxes
- AdminTranslations
- AdminParentModulesSf
- CONFIGURE
- ShopParameters
- AdminParentPreferences
- AdminParentOrderPreferences
- AdminPPreferences
- AdminParentCustomerPreferences
- AdminParentStores
- AdminParentMeta
- AdminParentSearchConf
- AdminAdvancedParameters
- AdminInformation
- AdminPerformance
- AdminAdminPreferences
- AdminEmails
- AdminImport
- AdminParentEmployees
- AdminParentRequestSql
- AdminLogs
- AdminWebservice
- AdminShopGroup
- AdminShopUrl
- ShopParameters
- DEFAULT
Как проверить регистрацию вкладок
Когда вы закончите, просто установите (или сбросьте) ваш модуль.
Свойство $tabs
будет прочитано из PrestaShop, и вкладки будут автоматически отображаться в боковом меню. Они останутся там, пока ваш модуль установлен.
Права доступа к вкладкам и роли
Когда вы создаете новую Tab
, она автоматически создает соответствующие роли в Tab::initAccess
на основе class_name
. Например, использование AdminLinkWidget
в качестве имени класса создаст следующие роли:
ROLE_MOD_TAB_ADMINLINKWIDGET_CREATE
ROLE_MOD_TAB_ADMINLINKWIDGET_DELETE
ROLE_MOD_TAB_ADMINLINKWIDGET_READ
ROLE_MOD_TAB_ADMINLINKWIDGET_UPDATE
Эти роли позволят вам управлять детализированными разрешениями в ваших контроллерах. Вы можете прочитать эту документацию, если вам нужно больше деталей о безопасности контроллеров. Они автоматически добавляются в группу SUPER_ADMIN
и в группу Сотрудника, устанавливающего модуль, но вы можете затем редактировать привилегии для других групп Сотрудников.
Скрытые вкладки
Вкладки обычно видимы и доступны в меню, но также существуют невидимые вкладки, они создаются только для управления безопасностью. Все контроллеры, присутствующие в controllers/admin
в вашем модуле, автоматически добавляются как скрытые вкладки (если не существует видимой вкладки).
Автоматическое скрытие отключенных модулей
Начиная с версии 1.7.7, когда вы отключаете модуль, все связанные с ним вкладки автоматически скрываются из меню административной панели.
Вкладки сохраняются в базе данных с полем enabled
, установленным в false
. Как только модуль снова включен, все его вкладки автоматически включаются.
Современные контроллеры
Ручная вставка вкладки
Если вы создали современный контроллер, используя контроллеры Symfony и маршрутизацию, вы не можете создать вкладку как есть, потому что система основана на устаревших контроллерах, идентифицированных через их имена классов. Но вы все равно можете обойти это, используя свойство _legacy_link
в маршрутизации (подробности об этой функции в странице маршрутизации контроллеров).
Предположим, вы уже определили свой маршрут Symfony:
# modules/your-module/config/routes.yml
your_route_name:
path: your-module/demo
methods: [GET]
defaults:
_controller: 'MyModule\Controller\DemoController::demoAction'
Что вам нужно сделать, так это добавить параметры _legacy_controller
и _legacy_link
:
# modules/your-module/config/routes.yml
your_route_name:
path: your-module/demo
methods: [GET]
defaults:
_controller: 'MyModule\Controller\DemoController::demoAction'
_legacy_controller: 'MyModuleDemoController'
_legacy_link: 'MyModuleDemoController'
Теперь любой вызов в системе меню к Link::getAdminLink('MyModuleDemoController')
вернет URL вашего контроллера your-module/demo
. Но так как класс MyModuleDemoController
на самом деле не существует, автоматическая регистрация вкладки на основе свойства $tabs
не сработает. Поэтому вам нужно вручную вставить вашу вкладку во время установки модуля:
<?php
use Language;
class Example_module_mailtheme extends Module
{
public function install()
{
return parent::install()
&& $this->installTab()
;
}
public function uninstall()
{
return parent::uninstall()
&& $this->uninstallTab()
;
}
public function enable($force_all = false)
{
return parent::enable($force_all)
&& $this->installTab()
;
}
public function disable($force_all = false)
{
return parent::disable($force_all)
&& $this->uninstallTab()
;
}
private function installTab()
{
$tabId = (int) Tab::getIdFromClassName('MyModuleDemoController');
if (!$tabId) {
$tabId = null;
}
$tab = new Tab($tabId);
$tab->active = 1;
$tab->class_name = 'MyModuleDemoController';
// Только с версии 1.7.7, можно определить имя маршрута
$tab->route_name = 'admin_my_symfony_routing';
$tab->name = array();
foreach (Language::getLanguages() as $lang) {
$tab->name[$lang['id_lang']] = $this->trans('My Module Demo', array(), 'Modules.MyModule.Admin', $lang['locale']);
}
$tab->id_parent = (int) Tab::getIdFromClassName('ShopParameters');
$tab->module = $this->name;
return $tab->save();
}
private function uninstallTab()
{
$tabId = (int) Tab::getIdFromClassName('MyModuleDemoController');
if (!$tabId) {
return true;
}
$tab = new Tab($tabId);
return $tab->delete();
}
}
Теперь у вас есть ссылка меню, указывающая на ваш контроллер Symfony с красивым URL.
Автоматическая регистрация вкладок
Современные контроллеры также могут быть зарегистрированы через свойство $tabs
. В этом случае вам не нужно вручную создавать объект вкладки, и вы можете полностью использовать маршрутизацию Symfony (без необходимости в _legacy_link
).
Вот пример с контроллером Symfony (пример взят из модуля ps_linklist). В этом контроллере нет ничего специфического, но обратите внимание на аннотацию безопасности @AdminSecurity
, которая использует request.get('_legacy_controller')
, что создаст связь между этим контроллером и конфигурацией маршрутизации.
<?php
// yourmodule/src/Controller/Admin/Improve/Design
namespace PrestaShop\Module\LinkList\Controller\Admin\Improve\Design;
use PrestaShopBundle\Security\Annotation\AdminSecurity;
// (...)
class LinkBlockController extends FrameworkBundleAdminController
{
/**
* @AdminSecurity("is_granted('read', request.get('_legacy_controller'))", message="Access denied.")
*
* @param Request $request
*
* @return Response
*/
public function listAction(Request $request)
{
// (...)
}
}
Теперь вот конфигурация маршрутизации. Мы видим, что опция _legacy_controller
присутствует со значением AdminLinkWidget
. Это будет использоваться для аннотации AdminSecurity
, а также в качестве class_name
нашей вкладки.
# yourmodule/config/routes.yml
admin_link_block_list:
path: /link-widget/list
methods: [GET]
defaults:
_controller: 'PrestaShop\Module\LinkList\Controller\Admin\Improve\Design\LinkBlockController::listAction'
# _legacy_controller используется для управления правами доступа
_legacy_controller: AdminLinkWidget
# В этом случае _legacy_link не требуется
Наконец, вот свойство $tabs
, используемое для автоматической регистрации. Оно по-прежнему требует поля class_name
: оно будет использоваться для создания стандартных AUTHORIZATION_ROLES
, связанных с этим class_name
, а затем для проверки этих разрешений.
<?php
// yourmodule/ps_linklist.php
use Language;
class Ps_Linklist extends Module
{
public function __construct() {
// ...
$tabNames = [];
foreach (Language::getLanguages(true) as $lang) {
$tabNames[$lang['locale']] = $this->trans('Link List', array(), 'Modules.Linklist.Admin', $lang['locale']);
}
$this->tabs = [
[
'route_name' => 'admin_link_block_list',
'class_name' => 'AdminLinkWidget',
'visible' => true,
'name' => $tabNames,
'parent_class_name' => 'AdminParentThemes',
'wording' => 'Link List',
'wording_domain' => 'Modules.Linklist.Admin'
],
];
// ...
}
}
Скрытые вкладки
Начиная с версии 1.7.7, когда вы создаете маршрут Symfony с _legacy_controller
, если не создана видимая вкладка, автоматически создается невидимая, чтобы разрешения были корректно обработаны.