Symfony 6 and EasyAdmin 4: Admin Panel for User Management System
Tags: php, security, authentication, symfony
Published: 2022-11-11 11:57:22

## Summary

[EasyAdmin](https://symfony.com/bundles/EasyAdminBundle/current/index.html) enables you to create admin panel bound to storage such as RDBMS easily.

It is one of the bundles of [Symfony](https://symfony.com/), a powerful and flexible [PHP](https://www.php.net/) framework, also requiring [Doctrine](https://www.doctrine-project.org/) ORM entities.

This post shows how to implement admin panel for user management system with Symfony and EasyAdmin.

### Environment

- [Alpine Linux](https://www.alpinelinux.org/) [3.16](https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.16.0) (on [Docker](https://www.docker.com/))
- PHP [8.1](https://www.php.net/releases/8.1/)
- Symfony [6.1](https://symfony.com/releases/6.1)
- [MariaDB](https://mariadb.org/) [10.9](https://mariadb.com/kb/en/mariadb-server-109/)

### Reference

- [Symfony EasyAdminBundle 4.x](https://symfony.com/bundles/EasyAdminBundle/4.x/index.html)
- [Symfony Form Events](https://symfony.com/doc/6.1/form/events.html)

## Tutorial

### Overview

In order to create admin panel, you need to take the 4 steps:

1. Preparation
2. Create dashboard
3. Introduce access control
4. Create a CRUD page

Here we go.

### 1. Preparation

#### 1-1. Build up user management system with Symfony SecurityBundle

Follow my previous post:

{% post nabbisen/symfony-6-user-authentication-4ek %}

#### 1-2. Install dependency

According to their [Design](https://symfony.com/bundles/EasyAdminBundle/4.x/design.html) page:

> The design of the backend is ready for any kind of application.

> all managed by Webpack via Symfony's Webpack Encore.

Install the bundle:

```console
$ php composer require \
      symfony/webpack-encore-bundle
```

#### 1-3. Install EasyAdmin bundle

Here is the main command line for getting started :)

```console
$ composer require easycorp/easyadmin-bundle
```

The output was:

```console
Info from https://repo.packagist.org: #StandWithUkraine
Using version ^4.4 for easycorp/easyadmin-bundle
./composer.json has been updated
Running composer update easycorp/easyadmin-bundle
Loading composer repositories with package information
Restricting packages listed in "symfony/symfony" to "6.1.*"
Updating dependencies
Lock file operations: 3 installs, 0 updates, 0 removals
  - Locking easycorp/easyadmin-bundle (v4.4.2)
  - Locking symfony/polyfill-uuid (v1.26.0)
  - Locking symfony/uid (v6.1.5)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 3 installs, 0 updates, 0 removals
  - Downloading symfony/polyfill-uuid (v1.26.0)
  - Downloading symfony/uid (v6.1.5)
  - Downloading easycorp/easyadmin-bundle (v4.4.2)
  - Installing symfony/polyfill-uuid (v1.26.0): Extracting archive
  - Installing symfony/uid (v6.1.5): Extracting archive
  - Installing easycorp/easyadmin-bundle (v4.4.2): Extracting archive
Generating optimized autoload files
112 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

Symfony operations: 1 recipe (25a03525415bea10d26670af31f4672d)
  - Configuring easycorp/easyadmin-bundle (>=3.0): From github.com/symfony/recipes:main
Executing script cache:clear [OK]
Executing script assets:install public [OK]
              
 What's next? 
              

Some files have been created and/or updated to configure your new packages.
Please review, edit and commit them: these files are yours.

No security vulnerability advisories found
```

#### 1-4. (Optional) Install additional modules

They are useful to customize forms:

```console
$ php composer require \
      symfony/form \
      symfony/validator
```

### 2. Create dashboard

#### 2-1. Generate dashboard modules

Happily, they provide useful maker commands. Run:

```console
$ php bin/console make:admin:dashboard
```

That's it.

You will be asked some questions. Here, I chose the default at all:

```console
 Which class name do you prefer for your Dashboard controller? [DashboardController]:
 > 

 In which directory of your project do you want to generate "DashboardController"? [src/Controller/Admin/]:
 > 


                                                                                                                        
 [OK] Your dashboard class has been successfully generated.                                                             
                                                                                                                        

 Next steps:
 * Configure your Dashboard at "src/Controller/Admin/DashboardController.php"
 * Run "make:admin:crud" to generate CRUD controllers and link them from the Dashboard.
```

Now you can connect to `https://(your-domain)/admin`. However, there must be no menus, while welcome messages are shown.

![welcome to easyadmin](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j5bhnq3gwcn9nzygvqes.png)

#### 2-2. Build up dashboard for use

First, create the view. Run:

```console
$ mkdir templates/admin

$ nvim templates/admin/index.html.twig
```

Then write in it just as below:

```diff
+ {% extends '@EasyAdmin/page/content.html.twig' %}
```

Next, edit the controller (`src/Controller/Admin/DashboardController.php`):

```diff
  class DashboardController extends AbstractDashboardController
  {
      #[Route('/admin', name: 'admin')]
      public function index(): Response
      {
+         return $this->render('admin/index.html.twig');
-         return parent::index();
-         // return parent::index();
```

Finally, generate frontend assets:

```console
$ yarn encore dev
$ # alternatively, `npm run dev` is available
```

Open again. Your dashboard must have become your own (almost blank for now).

![dashboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yps922zrghx3l78x1j44.png)

#### 2-3. Introduce access control

Be sure to implement access control if you prevent those who are not authenticated from using your admin panel:

```diff
  security:
      # ...
      access_control:
          # ...
+         - { path: ^/admin, roles: ROLE_USER }
```

Besides, above, you can use `ROLE_ADMIN` instead of `ROLE_USER` when your user is admin.

### 4. Create a CRUD page

#### 4-1. Generate crud modules

Thanks to them, it is also a single command line. Run:

```console
$ php bin/console make:admin:crud
```

The output was below. Choose your user entity at the first question:

```console
 Which Doctrine entity are you going to manage with this CRUD controller?:
  [0] App\Entity\User
 > 0

 Which directory do you want to generate the CRUD controller in? [src/Controller/Admin/]:
 > 

 Namespace of the generated CRUD controller [App\Controller\Admin]:
 > 

                                                                                                                        
 [OK] Your CRUD controller class has been successfully generated.                                                       
                                                                                                                        

 Next steps:
 * Configure your controller at "src/Controller/Admin/UserCrudController.php"
 * Read EasyAdmin docs: https://symfony.com/doc/master/bundles/EasyAdminBundle/index.html
```

#### 4-2. Customize crud modules

In order to add a menu for user CRUD to the dashboard, edit `src/Controller/Admin/DashboardController.php`:

```diff
+ use App\Entity\User;
  # ...
  class DashboardController extends AbstractDashboardController
  {
      # ...
      public function configureMenuItems(): iterable
      {
-         // yield MenuItem::linkToCrud('The Label', 'fas fa-list', EntityClass::class);
+         yield MenuItem::linkToCrud('User', 'fas fa-list', User::class);
```

That's it!

#### (Optional) 4-3. User password management

You may want to implement password changer with it hashed:

{% post nabbisen/symfony-6-and-easyadmin-4-hashing-password-3eec %}

### 5. View in browser

Let's go to the dashboard again and click the User menu. Voilà!

![admin panel for user management](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gaoxxvlbdwg0mt4nv5tg.png)

Here comes the power🔥 to create/update/delete users in your app via browser🌟