Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Страница панели на Symfony

Новые страницы панели управления пишут так же, как в обычном проекте на Symfony: маршрут связывает адрес с методом контроллера, контроллер готовит данные, шаблон Twig рисует страницу. Сделаем так страницу статистики отзывов. Для этого урока нужны автозагрузка и служба из предыдущего.

Что создаём

modules/acmehello/
├── config/
│   ├── routes.yml
│   └── services.yml
├── src/
│   ├── Controller/
│   │   └── Admin/
│   │       └── StatsController.php
│   └── Repository/
│       └── ReviewRepository.php
└── views/
    └── templates/
        └── admin/
            └── stats.html.twig

Все три файла создают вручную.

Маршрут

# modules/acmehello/config/routes.yml
acmehello_stats:
  path: /acmehello/stats
  methods: [GET]
  defaults:
    _controller: 'Acme\Hello\Controller\Admin\StatsController::indexAction'
    _legacy_controller: AdminAcmehelloStats
    _legacy_link: AdminAcmehelloStats

acmehello_stats — имя маршрута, path — адрес, _controller — класс и метод, который отвечает. _legacy_controller связывает маршрут с вкладкой и правами доступа, а _legacy_link позволяет строить ссылку привычным getAdminLink('AdminAcmehelloStats').

К адресам модулей движок добавляет приставку /modules, поэтому страница откроется по адресу вида /admin437xyz/index.php/modules/acmehello/stats.

Контроллер

<?php
// modules/acmehello/src/Controller/Admin/StatsController.php
namespace Acme\Hello\Controller\Admin;
 
use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;
use Symfony\Component\HttpFoundation\Response;
 
class StatsController extends FrameworkBundleAdminController
{
    public function indexAction(): Response
    {
        return $this->render('@Modules/acmehello/views/templates/admin/stats.html.twig', [
            'layoutTitle' => 'Статистика отзывов',
        ]);
    }
}

Метод возвращает объект ответа. render() собирает его из шаблона; путь начинается с @Modules и имени модуля.

Шаблон

{# modules/acmehello/views/templates/admin/stats.html.twig #}
{% extends '@PrestaShop/Admin/layout.html.twig' %}
 
{% block content %}
  <div class="card">
    <h3 class="card-header">Отзывы</h3>
    <div class="card-body">
      <p>Здесь будет статистика.</p>
    </div>
  </div>
{% endblock %}

Шаблон наследует общий макет панели: меню, шапка и заголовок страницы подставляются сами. Содержимое пишут в блоке content.

Вкладка

Добавьте страницу в свойство tabs главного класса и укажите имя маршрута:

// modules/acmehello/acmehello.php
[
    'name' => 'Статистика отзывов',
    'class_name' => 'AdminAcmehelloStats',
    'route_name' => 'acmehello_stats',
    'parent_class_name' => 'AdminCatalog',
    'visible' => true,
],

Сбросьте модуль и очистите кеш:

php bin/console prestashop:module reset acmehello
php bin/console cache:clear

В разделе «Каталог» появится пункт «Статистика отзывов», по нажатию откроется страница с карточкой.

Данные из службы

// modules/acmehello/src/Controller/Admin/StatsController.php
public function indexAction(): Response
{
    $repository = $this->get('acme.hello.review_repository');
 
    return $this->render('@Modules/acmehello/views/templates/admin/stats.html.twig', [
        'layoutTitle' => 'Статистика отзывов',
        'total' => $repository->countAll(),
        'latest' => $repository->findLatest(5),
    ]);
}
{% block content %}
  <div class="card">
    <h3 class="card-header">Всего отзывов: {{ total }}</h3>
    <div class="card-body">
      <ul>
        {% for review in latest %}
          <li>{{ review.author }} — {{ review.rating }}/5</li>
        {% else %}
          <li>Отзывов пока нет.</li>
        {% endfor %}
      </ul>
    </div>
  </div>
{% endblock %}

На странице появится общее число отзывов и пять последних. Twig экранирует переменные сам.

Ссылки и сообщения

Вызов в контроллереЧто делает
$this->generateUrl('acmehello_stats')Адрес маршрута с токеном
$this->redirectToRoute('acmehello_stats')Перенаправление на маршрут
$this->addFlash('success', 'Готово')Зелёное сообщение на следующей странице
$this->trans('Текст', 'Modules.Acmehello.Admin')Перевод строки

В шаблоне ссылку строит функция {{ path('acmehello_stats') }}.

Права доступа

Перед методом контроллера ставят аннотацию @AdminSecurity("is_granted('read', request.get('_legacy_controller'))") из пространства имён PrestaShopBundle\Security\Annotation. Она проверяет, что у профиля сотрудника есть право просмотра вкладки.

Отличия PrestaShop 9

В версии 9 базовый класс называется PrestaShopAdminController, службы передают в аргументы метода или конструктор, а не получают через $this->get(), а вместо аннотаций используют атрибуты PHP. Маршруты и шаблоны остаются теми же.

Частая ошибка

Маршрут добавили, а страница отдаёт «No route found». Маршруты кешируются вместе с контейнером, и модуль должен быть установлен и включён, иначе его routes.yml не читается. Очистите кеш и проверьте список командой php bin/console debug:router, найдя в выводе acmehello_stats.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.