EasyAdminBundle - Setup and Category Configuration
We've created a basic front end to display our available Categories, and any Wallpapers that we have added to those categories.
However, up until now, adding a new Wallpaper has only been possible by way of either our console command, or our Doctrine Fixtures.
In this video we are going to get started adding in an Admin area, where we can Create, Read (or List), Update, and Delete (CRUD!) both our wallpapers and our categories.
Back in the olden days, long before modern frameworks appeared, I will confess to avoiding the creation of an Admin area for as long as possible. There are a bunch of reasons for this:
- Building an admin area is a lot of work, none of which our end users ever see (we hope!);
- More code = more potential bugs = more time lost not improving our actual site;
- Security - if there's no admin area, there's no need to secure it!
To be clear, this was a good few years ago, at least 7 years as best I recall.
My solution to the problem of not having an Admin area was really simple:
I used my database GUI.
For the longest while this was PhpMyAdmin. I often didn't need to bother installing this - in the days when I used cPanel on my servers it was a handy one-click-install option.
When I started managing my own servers I would still install PhpMyAdmin as one of my first tasks. And that was all done manually, no Ansible back then.
My logic was this: PhpMyAdmin gave me full access to everything I needed to do. Sure, relating data together was a bit painful, but here was a tool that had 90% of what I would want in an Admin area, and it was easily secured (with a login screen) to boot.
A little later I moved to using installed database GUI clients, and I found that even more preferable as I didn't have to install PhpMyAdmin.
But when I started venturing out into client work, I couldn't rightly advise end users of my software to "just install SQLYog, or Sequel Pro" and that be a viable solution. If only.
Fast-forwarding this story somewhat, when starting with Symfony 2 we no longer worked so directly with the database. Instead we could create our Entities, and from there we could generated a CRUD boilerplate. Whilst tweaking would inevitably be required, this process alone saved hours of repetitive grunt work in setting up the basics for each entity.
With Symfony's security setup, we could secure off this CRUD section, and within a short amount of time, we had a rudimentary working Admin area.
The code behind this Admin area uses conventional Symfony-style PHP just like the user-visible side of our application / web site. In other words, if you are comfortable with Symfony's forms from working on the front end then you will feel right at home working on the Admin section.
Still, managing our own Admin area is more code for us to maintain. It's very repetitive code at that.
And even though it's an admin area, client expectations are still high. The client might want to use the admin panel on their mobile phone, so you end up spending hours making sure the admin section is responsive. All that effort so one manager can take a 5 second glance once a week... urgh.
Ok, so hopefully at this point you aren't regretting your life choices. I am about to offer a solution :)
Enter EasyAdminBundle
One of the many benefits of using Symfony as your framework of choice is that the code that makes up the framework has been created by some very smart people.
An extra hidden benefit to this is that this code has been reviewed by many more equally smart, or smarter people.
It's a real win-win, and is one of the reasons why I love Symfony - it allows me to stand on the shoulders of giants.
With this in mind, wouldn't it be nice if there was an Admin 'plugin' for any Symfony 2 or Symfony 3 website that had equally been created, and reviewed by smart people from the Symfony community?
Of course it would :)
And so, if you haven't already seen or heard of it, allow me to introduce EasyAdminBundle by Javier Eguiluz (and contributors).
Here we have a bundle that, with very little configuration on our part, gives us a high quality, fast and easy to use Admin panel. Oh, and it's fully responsive so no need to lose a bunch of valuable life on that either.
Enough talking from me, let's add the EasyAdminBundle to our project, and see just how easy it really is:
composer require javiereguiluz/easyadmin-bundle
We need to add the bundle to our project. We do so with composer
.
Once that's downloaded, we can enable the Bundle in our project's AppKernel.php
:
# /app/AppKernel.php
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = [
// symfony standard bundles here
new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(),
new Knp\Bundle\PaginatorBundle\KnpPaginatorBundle(),
new JavierEguiluz\Bundle\EasyAdminBundle\EasyAdminBundle(),
new AppBundle\AppBundle(),
];
// * snip *
Easy enough so far, right?
We don't need to create any controllers or generate any CRUD here. But we do need to tell our Symfony project that we want to use the controller provided by EasyAdminBundle
:
# /app/config/routing.yml
# new
easy_admin_bundle:
resource: "@EasyAdminBundle/Controller/"
type: annotation
prefix: /admin
# existing
app:
resource: '@AppBundle/Controller/'
type: annotation
Note here the use of the prefix
key.
This means that any actions that hit this controller are going to, at the very least, look something like:
http://oursite.whatever/admin
There's a couple of interesting points to make here.
Firstly, as soon as you add this new routing configuration you will get two new entries in your debug:routing
output:
-------------------------- -------- -------- ------ -----------------------------------
Name Method Scheme Host Path
-------------------------- -------- -------- ------ -----------------------------------
easyadmin ANY ANY ANY /admin/
admin ANY ANY ANY /admin/
-------------------------- -------- -------- ------ -----------------------------------
I've removed the other output for clarity.
Note though, both easyadmin
and admin
reference the same controller action.
Secondly, if you read the code from the above link, you will see a completely different method of using Symfony controller actions.
To finish off the installation phase we need to install the bundle's assets:
php bin/console assets:install --symlink
That's the installation part of this done. Now we need to add in our configuration.
Creating A Symfony Admin Panel With EasyAdminBundle
If you have your web server up and running at this point, and you try to hit the /admin
route then you will be greeted with the following:
The backend is empty because you haven't configured any Doctrine entity to manage. Solution: open your "app/config/config.yml" file and configure the backend under the "easy_admin" key.
500 Internal Server Error - NoEntitiesConfiguredException
A very helpful error message, as it happens.
One thing I'm going to alter from this suggestion is to separate my configuration out of config.yml
. To do this, first I will create a new file:
app/config/config/easy_admin_bundle.yml
And then update config.yml
to import
this new configuration file:
# /app/config/config.yml
imports:
- { resource: config/easy_admin_bundle.yml }
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
Before I go on, two things to address:
Yes, I appreciate config/config
sucks. But I couldn't think of a better name, and this is accurate enough for me. Feel free to change as needed, or leave your alternatives in the comments below. I'm always happy to rethink my approach.
Secondly, why split out the config?
The reasoning for this is two-fold.
Firstly, I prefer isolating everything if at all possible. If changes are made to config.yml
then they very well may break everything. It's easier to spot this if changes happen to this file infrequently.
Secondly, on larger projects I have found the easy_admin
config can become quite large. This becomes extra 'noise' to me when working on other parts of the project that still require me to edit config.yml
.
It's all personal preference of course, feel free to do all of this inside config.yml
.
Anyway, on we go:
# /app/config/config/easy_admin_bundle.yml
easy_admin:
entities:
Category:
class: AppBundle\Entity\Category
The easiest way to get started is to do the very least we can do.
In this case, the Category entity is the most simple of the two entities we have so far.
For each entity we wish to manage in our Admin panel, we need to add an entry under the entities
key.
Whatever key we give under entities
becomes the 'thing' we are working with. In our case, Category
is our entity name, so Category is the key I use.
These two do not need to match up. I could have done:
# /app/config/config/easy_admin_bundle.yml
easy_admin:
entities:
Lemonade:
class: AppBundle\Entity\Category
And this would still work, albeit in a much more confusing fashion :)
That's enough to get us going.
If we now browse to our site:
http://127.0.0.1:8000/admin
We will be redirect to:
http://127.0.0.1:8000/admin/?action=list&entity=Category
And again, I would recommend a perusal of the source code for this controller action as it really is quite an interesting journey.
You should now be able to Create new Category
entities, and both edit and delete existing Categories.
Also, you can search and sort, and whilst not immediately obvious, paginate too.
Very, very cool.