Symfony2 Admin panel in 30 seconds?
Posted on: 2015-01-21 | Categories:
PHP
Just few weeks ago i have introduced nice CRUD generator for generating basic admin scaffold. Today I have something even more interesting: Easy Symfony2 Admin panel generator. According to the documentation we should be able to generate complete and good looking admin panel in about 30 seconds (not including the installation and configuration). I decided to give this bundle a shot.
Before we start
Notice: This is a basic introduction to EasyAdminBundle
. If you want more, read about advanced customizations and EasyAdminBundle
integrations in More with EasyAdminBundle blog entry.
Before we create our admin panel there are some bundles that need to be installed and necessary configuration that needs to be set.
Create new project
As usually at the beginning we should create new Symfony2 project (installation step by step):
|
$ composer create-project symfony/framework-standard-edition sfEasyAdmin |
At the end of installation process you will be ask for DB connection configuration.
After that database should be created with command (if you haven’t done it yet manually):
|
$ php app/console doctrine:database:create |
Notice: According to the Symfony2 best practices after generating new project we have now brand new AppBundle where we should place our application logic. That’s why we are not going to create any other bundles.
Another notice: After installation we also need to enable app translator in app/config/config.yml
with:
|
framework: translator: { fallback: "%locale%" } |
Install FOSUserBundle
I recommend installing FOSUserBundle
for easy user management and also sign in / registration / password reset support for Symfony2 applications.
We need at least one entity. Let’s create empty User
entity class that later will be extended with FOSUser
model (we will also use that class to allow access to restricted areas of our app):
|
$ php app/console doctrine:generate:entity --entity=AppBundle:User --format=annotation --fields=" " --no-interaction |
Then install FOSUserBundle
through steps from documentation:
- install
FOSUserBundle
via composer
- enable it in
AppKernel.php
- configure
User
entity to extend FOSUser
model
- configure application security in
security.yml
file
- configure necessary
FOSUserBundle
configuration in config.yml file
- import
FOSUserBundle
routing files
After that we would need one User
with ROLE_ADMIN
credentials to access our admin application. This can be done with two simple Symfony2
shell and FOSUser
commands:
|
$ php app/console fos:user:create admin admin@level7systems.co.uk admin $ php app/console fos:user:promote admin ROLE_ADMIN |
Add Customer entity
Next step is to generate Customer
entity for storing customers data:
|
$ php app/console doctrine:generate:entity --entity=AppBundle:Customer --format=annotation --fields="name:string(255) firstName:string(255) lastName:string(255) phone:string(100) email:string(100) companyName:string(255) website:string(255) note:text" --no-interaction |
Notice: This is just sample entity. If you want you can generate for example blog entry or product entity.
Now we can update generated entities to add some relations:
- User should have their customers
- Customer should have its user (owner)
In User
entity we are going to add $customers
property:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
|
<?php namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; use FOS\UserBundle\Model\User as BaseUser; use Doctrine\Common\Collections\ArrayCollection; /** * User * * @ORM\Table() * @ORM\Entity */ class User extends BaseUser { // ... /** * @var ArrayCollection * * @ORM\OneToMany(targetEntity="AppBundle\Entity\Customer", mappedBy="user") */ protected $customers; /** * Constructor */ public function __construct() { $this->customers = new ArrayCollection(); } /** * Add customers * * @param \AppBundle\Entity\Customer $customers * @return User */ public function addCustomer(\AppBundle\Entity\Customer $customers) { $this->customers[] = $customers; return $this; } /** * Remove customers * * @param \AppBundle\Entity\Customer $customers */ public function removeCustomer(\AppBundle\Entity\Customer $customers) { $this->customers->removeElement($customers); } /** * Get customers * * @return \Doctrine\Common\Collections\Collection */ public function getCustomers() { return $this->customers; } } |
In Customer
entity we need to add $user
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
|
<?php namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; /** * Customer * * @ORM\Table() * @ORM\Entity */ class Customer { // ... /** * @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="customers") * * @var AppBundle\Entity\User; */ protected $user; // ... /** * Set user * * @param \AppBundle\Entity\User $user * @return Customer */ public function setUser(\AppBundle\Entity\User $user = null) { $this->user = $user; return $this; } /** * Get user * * @return \AppBundle\Entity\User */ public function getUser() { return $this->user; } } |
Update DB schema
Adding new entities and setting relations requires DB schema update:
|
$ php app/console doctrine:schema:update --force |
Install EasyAdminBundle
From project directory we can now call following command to download and install EasyAdmin
bundle:
|
$ composer require javiereguiluz/easyadmin-bundle |
Than enable it in app/AppKernel.php
file:
|
new JavierEguiluz\Bundle\EasyAdminBundle\EasyAdminBundle(), |
Load routes in app/config/routing.yml
:
|
easy_admin_bundle: resource: "@EasyAdminBundle/Controller/" type: annotation prefix: /admin |
And install Web Assets:
|
$ php app/console assets:install --symlink |
Easy Admin
After whole installation process we can configure entities for EasyAdmin
.
And this is where the magic begins: add this four lines to app/config/config.yml
file:
|
easy_admin: entities: - AppBundle\Entity\User - AppBundle\Entity\Customer |
And that’s it. We have ready to use admin panel created in a few seconds. What is more important we need proper credentials to sign in to our panel (thanks to FOSUser
bundle and Symfony2
security component).
Type following url in your browser:
http://localhost/sfEasyAdmin/web/app_dev.php/admin
and login with: admin / admin
credentials.
You should see Admin panel similar to this (click to zoom images):
We are ready! We can now create, edit and delete Users and Customers.
Notice: in the lower left corner, EasyAdmin
shows us the name of user who is currently logged in to the application.
Customization
As default configuration can be OK in some cases, in this example i want to update entities validation, forms and lists to display only that properties that we need.
Validation rules
By default our generated entities have no validation rules. If we want our properties to be required we should add e.g. NotBlank
constraint to User or Customer entities.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
<?php namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; /** * Customer * * @ORM\Table() * @ORM\Entity */ class Customer { // ... /** * @var string * * @ORM\Column(name="name", type="string", length=255) * * @Assert\NotBlank() */ private $name; // ... } |
It will display the appropriate message for empty name property:
Notice: Our generated entities by default have no constraints but also NULL values are not allowed, so saving empty form will cause NotNullConstraintViolationException
execpetion with message that given column value cannot be null. To fix that we should add proper constraint or allow NULL value for column.
Forms
As we can customize what fields should be displayed, there is no way to set field type for each property: we can also customize field type for each property (in this case for creating new user):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
easy_admin: entities: User: class: AppBundle\Entity\User edit: fields: ['username', 'email', 'enabled', 'locked'] new: fields: - { property: 'username' } - { property: 'email', type: 'email', label: 'E-mail address' } - { property: 'plainPassword', type: 'password' } - { property: 'enabled'} - { property: 'locked'} Customer: class: AppBundle\Entity\Customer new: fields: ['user', 'name', 'firstName', 'lastName', 'email', 'phone', 'companyName', 'website'] |
Customized view of creating new User
entity:
Lists
Using EasyAdmin
bundle configuration we can set which fields should be displayed on the list. That’s as easy as setting:
|
easy_admin: entities: User: class: AppBundle\Entity\User list: fields: ['id', 'username', 'email', 'enabled', 'locked', 'lastLogin'] |
We can also set proper data type for each column and use virtual properties
for better user experience.
More information about other settings and possible modifications can be found in bundle official documentation.
The complete source code can be found on GitHub.
Good luck with customizations!
shamali
May 14, 2015 07:09
Hi,
First thanks for sharing this information about easyadmin.I am new to symfony and have used this to generate admin panel for my project.My question is how can we implementjavascript validation with easyadmin ?
Kamil
May 14, 2015 07:44
Hi,
it is as simple as including you custom
JavaScript
file (as described in documentation) and implement you JavaScript validation. I can recommend you jQuery validate plugin which is very powerful and customizable.Cheers,
Kamil
Igor
May 16, 2015 14:28
Hi. Thank you for your post.
But please, remove snippet with class AdminController extends EasyAdminController. If you want to assign custom field types – there are built-in ability present for that.
I started with your snippet and spent 6 hours to learn internal structure of EasyAdminBundle because bundle does not work properly. And reason was found – that snippet. This not bad – now I know more about EasyAdminBundle’s structure, but… Better remove that snippet 🙂
Thank you.
Kamil
May 20, 2015 14:28
Hi Igor,
you’re right. EasyAdmin now offers a way to set a field type for each property. I have updated my blog entry. Thx.
Cheers,
Kamil
Martin
May 18, 2015 19:54
Hi!
Thanks for Your post regarding this nice admin generator. Let me allow to ask one question => at this moment when I’ll create new user object and click save in the database (Doctrine ORM) is saved all data including salt, but the password there is a plaintext (so no hashed). Can You help me to get out of this, or let’s say how to assure, that before persisting in database this hash calculation and setting-up to the object is done?
Thanks
Kamil
May 20, 2015 19:44
Hi Martin,
it depends on you configuration. If you are using master version of
FOSUserBundle
this could be achieved usingUserListener
which will handle the update of the password and the canonical fields for you behind the scenes. Check the documentation.Cheers,
Kamil
geo
April 27, 2016 23:14
Assuming you are integrating easyadmin with FOSUserBundle: To avoid the unhashed password change the field name in your easyadmin configuration to plainPassword.
ferrassi
September 29, 2015 11:09
Hi,
Did you tried sonata admin bundle ? which one is the best ?
Thank you.
peter
December 7, 2015 12:46
Hi,
I am also new to symfony 2 (lot’s of experience with symfony 1) and currently looking for the best admin generator solution for a new project that should be maintained for at least 5-10 years. Would you recommend easyadminbundle? Have you tried others (eg. sonata admin bundle?)
Thank you.
Kamil
July 3, 2016 20:50
Hi,
EasyAdmin is good but I’m using it for small projects. For the bigger one I can recommend SonataAdmin bundle v3.
Cheers,
Kamil
Kaizoku
June 9, 2016 08:45
I wordked with Sonata and EasyAdmin.
This is a no brain choice, use EasyAdmin.
SonataAdmin is full of flaws and not well documented.
EasyAdmin is newer, and well maintained.
Tomas
May 2, 2017 10:53
Thank you so much for such a wonderful article! It helped me a lot.