Коротко: EasyAdmin даёт быстрый CRUD-админ для Symfony из коробки; разбираем установку, Dashboard, CRUD-контроллер и подключение CKEditor.
EasyAdmin — бандл для быстрой админки в Symfony: из коробки даёт CRUD с простым нативным интерфейсом, что удобно в сжатые сроки. Разберём установку, создание дашборда и CRUD-контроллера, подключение CKEditor и типовые нюансы.
EasyAdmin Bundle предоставляет довольно простой CRUD с нативной визуализацией — это и делает его удобным под сжатые сроки.
Установка
composer require easycorp/easyadmin-bundle
Создание дашборда
Первым делом EasyAdmin предлагает создать главную страницу — так называемый Dashboard. Представим простое приложение с тремя сущностями: User, BlogPost и Category. Сотрудники компании могут создавать и редактировать любые из них, а внешние пользователи — только посты блога. В EasyAdmin это реализуется так:
- создать три CRUD-контроллера: UserCrudController, BlogPostCrudController, CategoryCrudController;
- создать DashboardController для сотрудников компании;
- создать ExternalDashboardController для внешних пользователей.
Технически все эти контроллеры сродни обычным контроллерам Symfony, поэтому в них доступны такие штуки, как $this->render() или $this->isGranted(). Классы дашбордов должны имплементировать EasyCorp\Bundle\EasyAdminBundle\Contracts\Controller\DashboardControllerInterface (он гарантирует наличие нужных методов) — либо расширять AbstractDashboardController и опираться на поведение по умолчанию.
Генерируем контроллер:
php bin/console make:admin:dashboard
Теперь на странице /admin появится приветственное окно.

Настройка меню и главной страницы
Дальше организуем меню и страницы. Переопределим шаблон дашборда в templates/admin/my-dashboard.html.twig:
{# templates/admin/my-custom-page.html.twig #}
{% extends '@EasyAdmin/page/content.html.twig' %}
{% block content_title %}The Title of the Page{% endblock %}
{% block page_actions %}
<a class="btn btn-primary" href="...">Some Action</a>
{% endblock %}
{% block main %}
<table class="datagrid">
<thead>
<tr>
<td>Some Column</td>
<td>Another Column</td>
</tr>
</thead>
<tbody>
</tbody>
</table>
{% endblock %}
И выставим примерно дефолтные значения в контроллере src/Controller/Admin/DashboardController:
<?php
namespace App\Controller\Admin;
use App\Entity\BlogPost;
use App\Entity\Category;
use App\Entity\User;
use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard;
use EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class DashboardController extends AbstractDashboardController
{
#[Route('/admin', name: 'admin')]
public function index(): Response
{
return $this->render('admin/my-dashboard.html.twig');
}
public function configureDashboard(): Dashboard
{
return Dashboard::new()
->setTitle('Otezvikentiy Tech');
}
public function configureMenuItems(): iterable
{
yield MenuItem::linkToDashboard('Dashboard', 'fa fa-home');
yield MenuItem::linkToCrud('Users', 'fas fa-user', User::class);
yield MenuItem::linkToCrud('Categories', 'fas fa-navicon', Category::class);
yield MenuItem::linkToCrud('Blog Posts', 'fas fa-newspaper', BlogPost::class);
}
}
Теперь админка примет примерно такой вид:

Подключение CKEditor
Чтобы удобно управлять сущностями, сразу установим CKEditor для EasyAdmin — это даст более приятный интерфейс для текстовых полей.
composer require friendsofsymfony/ckeditor-bundle
Убедимся, что загрузилась последняя версия CKEditor:
php bin/console ckeditor:install
И установим ассеты в папку public:
php bin/console assets:install public
Как сделать CRUD-контроллер?
Запускаем команду и следуем инструкциям:
php bin/console make:admin:crud
Команда создаст файл контроллера, который нужно донастроить. Сначала указываем, на какую сущность он ориентирован, через метод getEntityFqcn:
<?php
namespace App\Controller\Admin;
use App\Entity\BlogPost;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
class ArticleCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return BlogPost::class;
}
//...
}
Затем конфигурируем CRUD методом configureCrud:
public function configureCrud(Crud $crud): Crud
{
return $crud
->setEntityLabelInSingular('...')
->setDateTimeFormat('Y-m-d H:i:s')
->setTimezone('Europe/Moscow')
->renderContentMaximized()
->setEntityLabelInSingular('BlogPost')
->setEntityLabelInPlural('BlogPosts')
->setEntityPermission('ROLE_ADMIN')
->setSearchFields(['title', 'content', 'slug'])
->setDefaultSort(['id' => 'DESC'])
->setPaginatorPageSize(20)
->setPaginatorRangeSize(4)
->setPaginatorUseOutputWalkers(true)
->setPaginatorFetchJoinCollection(true)
->addFormTheme('@FOSCKEditor/Form/ckeditor_widget.html.twig')
;
}
Далее настраиваем поля сущности методом configureFields:
public function configureFields(string $pageName): iterable
{
return [
TextField::new('title'),
TextField::new('slug'),
ImageField::new('mainPicture')->setBasePath('images')->setUploadDir('public/images')->setRequired(false),
AssociationField::new('author')->setQueryBuilder(fn (QueryBuilder $queryBuilder) => $queryBuilder->getEntityManager()->getRepository(User::class)->findAll()),
AssociationField::new('category')->setQueryBuilder(fn (QueryBuilder $queryBuilder) => $queryBuilder->getEntityManager()->getRepository(Category::class)->findAll()),
AssociationField::new('tags')->setQueryBuilder(fn (QueryBuilder $queryBuilder) => $queryBuilder->getEntityManager()->getRepository(Tag::class)->findAll())->setFormTypeOption('by_reference', false),
TextareaField::new('content')->setFormType(CKEditorType::class),
];
}
У каждого поля свои настройки — полный список полей и опций есть в официальной документации EasyAdmin.
CKEditor можно кастомизировать — и внешне, и функционально — через их сайт: выбрать самый полный пресет, нужные плагины и скачать оптимизированную сборку. Полученный zip-архив распаковать в public/bundles/fosckeditor/*, предварительно очистив папку.
В процессе могут возникать ошибки вида «система пытается привести сущность к строке» — тогда добавьте в эту сущность магический метод __toString(), например так:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity()]
class BlogPost
{
//...
#[ORM\Column(length: 255, nullable: false)]
private string $title;
public function __toString(): string
{
return $this->title;
}
//...
}
Это базовая настройка EasyAdmin. Если нужно быстро поднять админку под проект или, наоборот, мигрировать с EasyAdmin на кастомное решение — помогу на консультации.


Комментарии