Summary
EasyAdmin enables you to create easily admin panel bound to storage such as RDBMS.
It is one of the bundles of Symfony, a powerful and flexible PHP framework, also requiring Doctrine ORM entities.
Environment
- OS: Alpine Linux 3.15
- Docker VM
- Web: Caddy 2
- App: EasyAdmin 4.0
- based on PHP 8.0, Symfony 6.0 and Doctrine 2.11
- DB: MariaDB 10.6
Tutorial
sudo
can be used instead of doas
below.
PHP
PHP8 and PHP-FPM
$ doas apk add php8-fpm
PHP extensions
$ doas apk add php8-gd php8-curl php8-dom php8-iconv php8-json php8-mbstring php8-openssl php8-pdo php8-session php8-tokenizer php8-session php8-xml php8-simplexml php8-xmlwriter php8-zip php8-ctype php8-intl php8-opcache php8-pcntl
Case SQLite3
$ doas apk add sqlite
$ doas apk add php8-pdo_sqlite
Case MariaDB
$ doas apk add mariadb-client
$ doas apk add php8-pdo_mysql php8-mysqlnd
PHP-FPM daemon
$ # enable
$ doas rc-update add php_fpm
$ # start
$ doas rc-service php_fpm start
Caddy
$ doas apk add caddy
$ # enable
$ doas rc-update add caddy
$ # start
$ doas rc-service caddy start
your.host
log {
output file "/var/log/caddy/caddy.log"
}
root * "/var/local/appbc/public"
@blocked {
path /.git*
}
respond @blocked 403
@assets {
path_regexp ^.*(\.html|\.css|\.js|\.jpg|\.jpeg|\.png|\.webp|\.gif|\.svg|\.woff2)$
}
file_server @assets
@approutes {
path_regexp ^.*/[^\./]*/?$
}
#rewrite @approutes /index.php?{query}&c={path}
rewrite @approutes /index.php?{query}
@indexphp {
path /index.php*
}
#php_fastcgi @indexphp "unix//run/php-fpm7/php-fpm.pid"
php_fastcgi @indexphp "127.0.0.1:9000"
Symfony
$ composer create-project symfony/website-skeleton "<project-dir>"
$ cd "<project-dir>"
EasyAdmin
Install
$ composer require easycorp/easyadmin-bundle
The output was:
Using version ^4.0 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.0.*"
Updating dependencies
Lock file operations: 3 installs, 0 updates, 0 removals
- Locking easycorp/easyadmin-bundle (v4.0.6)
- Locking symfony/polyfill-uuid (v1.24.0)
- Locking symfony/uid (v6.0.3)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 3 installs, 0 updates, 0 removals
- Downloading symfony/polyfill-uuid (v1.24.0)
- Downloading symfony/uid (v6.0.3)
- Downloading easycorp/easyadmin-bundle (v4.0.6)
- Installing symfony/polyfill-uuid (v1.24.0): Extracting archive
- Installing symfony/uid (v6.0.3): Extracting archive
- Installing easycorp/easyadmin-bundle (v4.0.6): Extracting archive
Generating optimized autoload files
110 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
Symfony operations: 1 recipe (...)
- Configuring easycorp/easyadmin-bundle (>=3.0): From github.com/symfony/recipes:master
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.
Create a Dashboard
Install
$ php bin/console make:admin:dashboard
I was asked a couple of times and used the default:
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.
Here, you can see the default dashboard!!
Well, there is no menu! Let's create your own dashboard and add menus to it.
Create the first dashboard of your own
Let's create a custom template:
$ mkdir templates/admin
$ nvim templates/admin/index.html.twig
Write just this in it:
+ {% extends '@EasyAdmin/page/content.html.twig' %}
Then, edit the controller (src/Controller/Admin/DashboardController.php
):
class DashboardController extends AbstractDashboardController
{
#[Route('/admin', name: 'admin')]
public function index(): Response
{
- return parent::index();
+ return $this->render('admin/index.html.twig');
Then prepare assets:
$ yarn encore dev
$ # alternatively, `npm run dev` is available
Besides, you sometimes have to clear cache.
$ php(8) bin/console cache:clear
Reload the dashboard page, and you will see it's replaced with your own.
There are few menus. Next, let's implement to manage table records.
Prepare an entity
Let's make some entity. It's dealt with by Symfony and Doctrine.
Use make bundle. You will be asked on its schema:
$ php bin/console make:entity
Then make it substantial:
$ php bin/console make:migration
$ # reply yes
$ php bin/console doctrine:migrations:migrate
$ # reply yes
Create a CRUD controller
It's EasyAdmin's turn.
$ php bin/console make:admin:crud
The output was:
Which Doctrine entity are you going to manage with this CRUD controller?:
[0] App\Entity\(...)
> 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/(...)CrudController.php"
* Read EasyAdmin docs: https://symfony.com/doc/master/bundles/EasyAdminBundle/index.html
Add a menu on the entity:
(...)
+ use App\Entity\SamplePack;
class DashboardController extends AbstractDashboardController
(...)
public function configureMenuItems(): iterable
{
yield MenuItem::linkToDashboard('Dashboard', 'fa fa-home');
- // yield MenuItem::linkToCrud('The Label', 'fas fa-list', EntityClass::class);
+ yield MenuItem::linkToCrud('The Label', 'fas fa-list', SamplePack::class);
}
Then, reload the page.
Yay, got it. Let's click "The Label" on the left side:
We can manage storage here!!
Conclusion
I tried a new feature released just at the beginning of the year, menu badges.
To show a count:
- yield MenuItem::linkToCrud('The Label', 'fas fa-list', SamplePackClass::class);
+ yield MenuItem::linkToCrud('The Label', 'fas fa-list', SamplePackClass::class)
+ ->setBadge(468, 'success');
Nice.
To show a message:
- yield MenuItem::linkToCrud('The Label', 'fas fa-list', SamplePackClass::class);
+ yield MenuItem::linkToCrud('The Label', 'fas fa-list', SamplePackClass::class)
+ ->setBadge('Ciao!', 'background: transparent; color: #44bb88; outline: 2px solid white');
Sweet 💃💃