Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Installing EasyAdmin

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

Well hey friends! We are in for a treat with this tutorial! It's EasyAdmin: my favorite admin generator for Symfony. It just... gives you so many features out of the box. And it looks great! This shouldn't really be a surprise because its creator is the always-impressive Javier Eguiluz.

So let's have some fun and learn how to bend EasyAdmin to our will. Because getting a lot of features for free is great... as long as we can extend it to do crazy things when we need to.

Project Setup

To squeeze the most "easy" out of EasyAdmin, you should definitely code along with me. You probably know the drill: download the course code from this page and unzip it to find a start/ directory with the same code that you see here. Check out the README.md file for all the setup goodies. I've already done all of these steps except for two.

For the first, find your terminal and run:

yarn install

I ran this already to save time... so I'll skip to compiling my assets with:

yarn watch

You can also run:

yarn dev-server

Which can do cool things like update your CSS without refreshing.

Perfect! For the second thing, open up another tab and run:

symfony serve -d

This fires up a local web server - using the Symfony binary - at https://127.0.0.1:8000. I'll be lazy by holding Cmd and clicking the link to pop open my browser. Say "hello" to... Cauldron Overflow! If you've been doing our Symfony 5 series, you're definitely familiar with this project. But, this is a Symfony 6 project, not Symfony 5:

100 lines composer.json
{
... lines 2 - 3
"require": {
... lines 5 - 15
"symfony/asset": "6.0.*",
"symfony/console": "6.0.*",
"symfony/dotenv": "6.0.*",
... line 19
"symfony/framework-bundle": "6.0.*",
... line 21
"symfony/runtime": "6.0.*",
"symfony/security-bundle": "6.0.*",
"symfony/stopwatch": "6.0.*",
"symfony/twig-bundle": "6.0.*",
... line 26
"symfony/yaml": "6.0.*",
... lines 28 - 29
},
"require-dev": {
... line 32
"symfony/debug-bundle": "6.0.*",
... line 34
"symfony/var-dumper": "6.0.*",
"symfony/web-profiler-bundle": "6.0.*",
... line 37
},
... lines 39 - 98
}

Oooo. If you are using Symfony 5, don't worry: very little will be different.

You don't need to worry too much about the majority of the code inside the project. The most important thing is probably our src/Entity/ directory. Our site has questions, and each Question has a number of answers. Each Question belongs to a single Topic... and then we have a User entity.

Our goal in this tutorial is to create a rich admin section that allows our admin users to manage all of this data.

Installing EasyAdmin

So let's get EasyAdmin installed! Find your terminal and run:

composer require admin

This is a Flex alias for easycorp/easyadmin-bundle. Notice that it downloads the shiny new version 4 of EasyAdmin, which only works with Symfony 6. So if you're using Symfony 5, run:

composer require admin:^3

to get version 3. Right now, version 4 and version 3 are identical, so you won't notice any differences. But going forward, new features will only be added to version 4.

Cool! Now that this is installed, what's next? Ship it!? Well, before we start deploying and celebrating our success... if we want to actually see something on our site, we're going to need a dashboard. Let's generate that next!

Leave a comment!

33
Login or Register to join the conversation
Ruslan Avatar

Thank you! :)

2 Reply
Andrzej S. Avatar
Andrzej S. Avatar Andrzej S. | posted 9 months ago

EasyAdmin 4 requires PHP 8.0.2 or higher and Symfony 5.4 or higher. Why did you say that it only for Symfony 6?

1 Reply

Hey Andrzej S.

I'm afraid there was a confusion. This tutorial uses Symfony 6 and PHP 8 but it doesn't mean that you can only run EasyAdmin on those versions. EasyAdmin comes with its own version constraints that you can check here https://github.com/EasyCorp...
I hope I managed to clarify the situation. Cheers!

1 Reply
Andrzej S. Avatar

Thanks for the reply, it's helpful.
By the way, I love your tutorials and I learned a lot from them.

Reply

Hi there,

I tried docker-compose up -d as in readme and I got the error

ERROR: Version mismatch: file ./docker-compose.yaml specifies version 3.7 but extension file ./docker-compose.override.yml uses version 3.0

Fixed the docker-composer.override.yml and it worked

1 Reply

Hey Rodrigo!

Sorry about that! It was fixed in https://github.com/SymfonyC... - thanks for head ups!

Cheers!

Reply
robspijkerman Avatar
robspijkerman Avatar robspijkerman | posted 5 months ago

Hi

I notice that Easy Admin has been updated since you did this tutorial, there is now no html.twig files and therefore no start point for creating the admin page which quite frankly makes it very difficult to proceed as it offers you 3 options that at this time mean very little therefore making it impossible to proceed further. Can you make this available for the tutorial please as it really confuses the whole start process.

Cheers

Rob

Reply
Estelle G. Avatar
Estelle G. Avatar Estelle G. | posted 6 months ago

Hi, first of all thanks a million for your awesome tutorials, truly love them.
I'm running into a bit of an issue during install here and would appreciate some help.

I've just downloaded the start archive & followed the install steps (without Docker), I'm currently using PHP 8.1.4. I've tried switching back to 8.0.12 & 8.1.2 (I'm using Laragon + manually updating Windows env vars) but the same error occurs.

However whenever I launch the Symfony server, I get the following error & unfortunately I'm unable to reach http://127.0.0.1:8000 - it never loads.

|CRITICA| REQUES Uncaught PHP Exception Twig\Error\RuntimeError: "An exception has been thrown during the rendering of a template ("Class "App\Entity\Category" does not exist")." at C:\Users\estel\Desktop\Symfony\SymfonyCasts\code-easyadminbundle\start\templates\base.html.twig line 18

When I go to base.html.twig :

{{ is_granted('ROLE_PREVIOUS_ADMIN') ? 'style="background-color: red !important"' }}

I've tried closing & reopening VSCode, symfony server:stop & symfony serve again, but to no avail. Any help appreciated :) TIA

Reply

Hey Estelle G.

That's a very odd error because the entity Category does not exist in this project. Did you change something after downloading the start directory?
Try clearing your cache rm -rf var/cache and reinstall your vendors rm -rf vendor && composer install
Oh, and if you're on Windows, try using "localhost" instead of "127.0.0.1"

Cheers!

Reply
Estelle G. Avatar

Thanks for your reply. Well I am not sure what happened, possibly some sort of witchcraft ahah but well anyway after restarting my PC & this project today it now works perfectly fine, but thank you anyway :)

Reply
Tien dat L. Avatar
Tien dat L. Avatar Tien dat L. | posted 6 months ago

Hallo, May i ask a question please?

I got missing translation messages in easyadmin 4

# symfony console debug:translation en --only-missing
State Domain Id Message Preview (en) Fallback Message Preview (de)
----------- ----------------- ------------------------ ------------------------ -------------------------------
missing time diff.empty diff.empty diff.empty
missing EasyAdminBundle label.form.empty_value label.form.empty_value label.form.empty_value

I tried in app/translation/messages.en.yaml:

label:
---- form:
-------- empty_value : abc

but still got missing, how can i fix this thanks

Reply
Tien dat L. Avatar

in vendor/easycorp/easyadmin-bundle/src/Resources/translations/EasyAdminBundle.de.php
->i found 'label' => 'form.emtyp_value' => 'keine Wert'

...

Reply

Hey Luong,

Hm, sounds like a type in the message key, right? Good catch! It's a great opportunity to create a PR to the EasyAdminBundle. Are you going to do this?

Cheers!

1 Reply
Tien dat L. Avatar
Tien dat L. Avatar Tien dat L. | victor | posted 6 months ago | edited

Hi @victor yes i try work around with symfony and easyadmin, is great :). But i dont know why i still got missing messager ?_? how can overrider translation von easyadmin in 'de' order fix this missing

1 Reply

Hey Luong,

Here's the link to the docs that shows how to override translations from third-party bundles: https://symfony.com/doc/cur... . But if there's a typo - it's better to send a PR and fix it upstream in the bundle's repo. Then, just upgrade to a new release that will contains those changes.

I hope this helps!

Cheers!

1 Reply

Bonjour! May I ask a question please?

I should use CAS bundle for my app because we use SSO system. So, can i use the following bundle while I use Symfony 6 because there is no CAS bundle for Symfony6:
https://github.com/ecphp/ca...

I really appreciate your support and your hard work! ^^

Reply

Hey Lubna,

Unfortunately, I've never worked with CAS protocol before, so don't use those bundles myself. But let me give you some hints. First of all, I see that the bundle you linked https://github.com/ecphp/ca... does not support Symfony 6 yet, though there's an issue about it: https://github.com/ecphp/ca... - feel free to follow it to know when that issue is closed. Also, if you have time - feel free to help with upgrading that bundle and make it compatible with Symfony 6 and send a PR - that may have a good side effect, because even if the bundle is slow on reviewing/merging your PR - you will be able to use *your* fork in your project while PR is not merged yet.

Other options - you may want to take a look at GitHub search: https://github.com/search?o... - probably you will find that is still maintained. If no luck - you may want to use low-level tools that are used in those bundles to write the implementation yourself - take a look at composer.json file to see what libs are used behind the scene in those bundles that might help you.

Or, another option - downgrade your project to Symfony 5.4. Basically, Symfony 5.4 == 6.0, but in Symfony 6.0 just dropped all the legacy code since 5.x version. Though, it might work and you will be able to install that bundle, but keep in mind that if the bundle is dead and nobody will add Symfony 6 support there - you won't be able to upgrade to the newer version at some point.

I hope this helps!

Cheers!

1 Reply

Many thanks for your helpful response! All is clear.

Reply

Hey Lubna,

Glad to hear it was helpful for you! And sorry that I can't help more with this problem

Cheers!

Reply

Hi again!

After downgrading my app I have a problem in my auth. Could you plz take a look at my error message as below:

An exception has been thrown during the rendering of a template ("Unable to find the current firewall LogoutListener, please provide the provider key manually.").

So, I had to add a logout path under the firewalls in my security.yaml file. Right now I can login but can't logout. Please note that I use sso auth.

Have you any idea about that?

Many thanks in advance and have a nice day!

Reply

Hey Lubna,

Please, take a look at the config/packages/security.yaml configuration, in particular, at the "logout" key there. Most probably you need to specify path key manually for logout option under your firewall there.

If you do so, and don't see that error anymore - great, but what error do you see now? What happens where you logging out?

Cheers!

Reply

Thanks for your reply! after clicking on logout nothing happens at all. I am still connected

Reply

Hey Lubna,

Well, still something should happen :) Were you followed the /logout path in the address bar of your browser? Were you redirected somewhere then? Could you show your logout configuration in your security.yaml? Also, your logout() route you created? Does it have something "throw new \Exception('This should never be reached')" inside or something like this?

Cheers!

Reply

Hey! thanks again.
yep I can find the redirected path while chlicking (mypath/logout) and see it in the address bar. Also, I added the logout route in my defult controller.

Reply

Hey Lubna,

Hm, ok... do you have a logout entry point like this?


/**
* @Route("/logout", name="app_logout")
*/
public function logout()
{
throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
}

Also, could you show your security firewall configuration?

Cheers!

Reply

Thanks again! I have the following route in my main controller:


#[Route('/logout', name: 'logout')]
public function logoutAction() {
if (($this->getParameter('cas_logout_target') !== null) && (!empty($this->getParameter('cas_logout_target')))) {
\phpCAS::logoutWithRedirectService($this->getParameter('cas_logout_target'));
} else {
\phpCAS::logout();
}
}

And here is my firewall config:


firewalls:
dev:
pattern: ^/(_(profiler|wdt|error)|css|images|js)/
security: false
l3_firewall:
pattern: ^/
security: true
cas: true # Activation du CAS
logout:
path: /logout
Reply

Hey Lubna,

Thanks for sharing more details! Hm, your config looks ok, but let's try to tweak it a bit... Could you try to rename your firewall name "l3_firewall" -> "main" in this config? Also, make sure you renamed "l3_firewall" with "main" in other parts of your application if you're referencing to it somewhere. Then, (and it's important steps next!), clear the cache, next reload your fixtures that should force logging out the current user, and finally log in again and try to logout. Still can't logout?

Cheers!

Reply

Thanks for your help! It still does not work. But to be honest, as the bundle instruction I shouldn't add the logout path as I did above. If I removed it, seems I have a problem in EasyAdmin. As below:

Twig\Error\
RuntimeError

in C:\Users\laltung1\Desktop\sites-prol3\vendor\easycorp\easyadmin-bundle\src\Resources\views\layout.html.twig (line 88)

Here is the line 88:
{% if null == ea.userMenu.avatarUrl %}

Reply

Hi Lubna !

I'm coming in here to see if I can help :). If I understand things correctly, the problem is that when you click "Log out"... you don't actually get logged out. Is that right?

If so, I think I see the problem. When you go to /logout, the "logout" part of the security system "intercepts" that, logs the user out "in Symfony" and then redirects the user. Normally, this is all you need. However, in your case, you *also* need to log out with cas. Here are 2 things that explain the weird behavior:

A) Because the "logout" functionality intercepts requests to /logout, your logout() action isn't ever executed. You can try putting. a "die" statement in there: it won't be hit. This means that when you go to /logout, you are not actually being logged out of CAS.
B) When you go to /logout, you ARE logged out of Symfony... but then Symfony redirects, and the "cas authenticator" immediately sees that you are still logged in via CAS and re-authenticates you. In other words, for a *moment*, after you go to /logout, you ARE logged out. But nearly instantly you are logged back in... and you never notice.

Anyways, here's what you need to do:

1) Remove your logic from the logout() action. This will never be executed. We usually put a giant exception in this method - like Victor showed - https://symfonycasts.com/sc... - because we know it won't be executed, and if it *were* executed, we would want to see this clear error (because it means something is wrong).

2) Create a class that implements LogoutSuccessHandlerInterface: https://github.com/symfony/... - inside onLogoutSuccess(), paste your custom cas logout logic (the stuff that was inside of the logout() controller until now). You won't be able to use $this->getParameter(), so you'll need to inject those via the constructor.

3) To use this handler, add this config under your firewall:


security:
# ...

firewalls:
l3_firewall:
# ...

logout:
success_handler: App\Security\CasLogoutSuccessHandler

Where App\Security\CasLogoutSuccessHandler is whatever you called your class :).

I know, a bit complex, but this is how your run code after logging out. in Symfony 6 (once the Cas bundle supports it), the code is a little different: you register a listener to LogoutEvent. But worry about that later - it'll be a small change.

Let me know. if that helps!

Cheers!

1 Reply
Jason A. Avatar
Jason A. Avatar Jason A. | posted 8 months ago

Perhaps this chapter could include a comment about if this is appropriate to use with API Platform, or if for API Platform one should use their react Admin package instead? https://api-platform.com/do...

Reply

Hey Jason A.

That's a good question and I think you can use both libraries in your project, but EasyAdmin won't use your API automatically on its CRUD operations, so, if your API has a different procedure than your admin interface for storing or updating something, then, I think it would be better to rely on the ApiPlatform admin package

Cheers!

Reply
akincer Avatar

Yet another tutorial very timely for my own project challenges. Thanks!

Reply

Yo! cool! We are happy to provide relevant courses!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=8.0.2",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "composer/package-versions-deprecated": "^1.11", // 1.11.99.4
        "doctrine/doctrine-bundle": "^2.1", // 2.5.5
        "doctrine/doctrine-migrations-bundle": "^3.0", // 3.2.1
        "doctrine/orm": "^2.7", // 2.10.4
        "easycorp/easyadmin-bundle": "^4.0", // v4.0.2
        "handcraftedinthealps/goodby-csv": "^1.4", // 1.4.0
        "knplabs/knp-markdown-bundle": "dev-symfony6", // dev-symfony6
        "knplabs/knp-time-bundle": "^1.11", // 1.17.0
        "sensio/framework-extra-bundle": "^6.0", // v6.2.5
        "stof/doctrine-extensions-bundle": "^1.4", // v1.7.0
        "symfony/asset": "6.0.*", // v6.0.1
        "symfony/console": "6.0.*", // v6.0.2
        "symfony/dotenv": "6.0.*", // v6.0.2
        "symfony/flex": "^2.0.0", // v2.0.1
        "symfony/framework-bundle": "6.0.*", // v6.0.2
        "symfony/mime": "6.0.*", // v6.0.2
        "symfony/monolog-bundle": "^3.0", // v3.7.1
        "symfony/runtime": "6.0.*", // v6.0.0
        "symfony/security-bundle": "6.0.*", // v6.0.2
        "symfony/stopwatch": "6.0.*", // v6.0.0
        "symfony/twig-bundle": "6.0.*", // v6.0.1
        "symfony/ux-chartjs": "^2.0", // v2.0.1
        "symfony/webpack-encore-bundle": "^1.7", // v1.13.2
        "symfony/yaml": "6.0.*", // v6.0.2
        "twig/extra-bundle": "^2.12|^3.0", // v3.3.7
        "twig/twig": "^2.12|^3.0" // v3.3.7
    },
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.3", // 3.4.1
        "symfony/debug-bundle": "6.0.*", // v6.0.2
        "symfony/maker-bundle": "^1.15", // v1.36.4
        "symfony/var-dumper": "6.0.*", // v6.0.2
        "symfony/web-profiler-bundle": "6.0.*", // v6.0.2
        "zenstruck/foundry": "^1.1" // v1.16.0
    }
}