Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine


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.

Hey friends! Welcome to Symfony 5 Fundamentals! I cannot emphasize enough, how important this course is to make you super productive in Symfony. And, well, I also think you're going to love it. Because we're going to really explore how your app works: services, configuration, environment, environment variables and more! These will be the tools that you'll need for everything else that you'll do in Symfony. After putting some work in now, anything else you build will feel much easier.

Ok! Let's go unlock some potential! The best way to do that - of course - is to download the course code from this page and code along with me. If you followed our first course, you rock! The code is basically where that course finished. But I recommend downloading the new code because I did make a few small tweaks.

After you unzip the download, you'll find a start/ directory with the same code that you see here. Head down to the fancy README.md for all the instructions on how you get your project set up... and, of course, a poem about magic.

The last step in the setup will be to find a terminal, move into the project and use the symfony executable to start a handy development web server. If you don't have this symfony binary, you can download it at https://symfony.com/download. I'll run:

symfony serve -d

to start a web server at localhost:8000. The -d means run as a "daemon" - a fancy way of saying that this runs in the background and I can keep using my terminal. You can run symfony server:stop later to stop it.

Ok! Spin over to your browser and go to https://localhost:8000 to see... Cauldron Overflow! Our question & answer site dedicated to Witches and Wizards. It's a totally untapped market.

Services do Everything

One of the things we learned at the end of the first course is that all the work in a Symfony app - like rendering a template, logging something, executing database queries, making API calls - everything is done by one of many useful objects floating around. We call these objects services. There's a router service, logger service, service for rendering Twig templates and many more. Simply put, a service is a fancy word for an object that does work.

And because services do work, they're tools! If you know how to get access to these objects, then you're very powerful. How do we access them? The primary way is by something called autowiring. Open up src/Controller/QuestionController.php and find the homepage() method:

... lines 1 - 9
class QuestionController extends AbstractController
* @Route("/", name="app_homepage")
public function homepage(Environment $twigEnvironment)
// fun example of using the Twig service directly!
$html = $twigEnvironment->render('question/homepage.html.twig');
return new Response($html);
return $this->render('question/homepage.html.twig');
... lines 26 - 42

We commented out the code that used it, but by adding an argument type-hinted with Environment, we signaled to Symfony that we wanted it to pass us the Twig service object:

... lines 1 - 7
use Twig\Environment;
class QuestionController extends AbstractController
... lines 12 - 14
public function homepage(Environment $twigEnvironment)
... lines 17 - 24
... lines 26 - 42

That's called autowiring.

And how did we know to use this exact Environment type hint to get the Twig service? And what other service objects are floating around waiting for us to use them and claim ultimate programming glory? Find your terminal and run:

php bin/console debug:autowiring

Boom! This is our guide. Near the bottom, it says that if you type-hint a controller argument with Twig\Environment, it will give us the Twig service. Another one is CacheInterface: use that type-hint to get a useful caching object. This is your menu of what service objects are available and what type-hint to use in a controller argument to get them.

Hello Bundles!

But where do these services come from? Like, who added these to the system? The answer to that is... bundles. Back in your editor, open a new file: config/bundles.php:

... lines 1 - 2
return [
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true],
Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true],

We'll see who uses this file later, but it returns an array with 8 class names that all have the word "Bundle" in them.

Ok, first, whenever you install one of these "bundle" things, the Flex recipe system automatically updates this file for you and adds the new bundle. For example, in the first course, when we installed this WebpackEncoreBundle, its recipe added this line:

... lines 1 - 2
return [
... lines 4 - 10
Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true],

The point is, this is not a file that you normally need to think about.

But... what is a bundle? Very simply: bundles are Symfony plugins. They're PHP libraries with special integration with Symfony.

And, the main reason that you add a bundle to your app is because bundles give you services! In fact, every single service that you see in the debug:autowiring list comes from one of these eight bundles. You can kind of guess that the Twig\Environment service down here comes from TwigBundle:

... lines 1 - 2
return [
... lines 4 - 5
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
... lines 7 - 11

So if I removed that TwigBundle line and ran the command again, the Twig service would be gone.

And yes, bundles can give you other things like routes, controllers, translations and more. But the main point of a bundle is that it gives you more services, more tools.

Need a new tool in your app to... talk to an API or parse Markdown into HTML? If you can find a bundle that does that, you get that tool for free.

In fact, let's do exactly that next.

Leave a comment!

This tutorial also works great for Symfony 6!

What PHP libraries does this tutorial use?

// composer.json
    "require": {
        "php": "^7.3.0 || ^8.0.0",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "knplabs/knp-markdown-bundle": "^1.8", // 1.9.0
        "sensio/framework-extra-bundle": "^6.0", // v6.2.1
        "sentry/sentry-symfony": "^4.0", // 4.0.3
        "symfony/asset": "5.0.*", // v5.0.11
        "symfony/console": "5.0.*", // v5.0.11
        "symfony/debug-bundle": "5.0.*", // v5.0.11
        "symfony/dotenv": "5.0.*", // v5.0.11
        "symfony/flex": "^1.3.1", // v1.17.5
        "symfony/framework-bundle": "5.0.*", // v5.0.11
        "symfony/monolog-bundle": "^3.0", // v3.6.0
        "symfony/profiler-pack": "*", // v1.0.5
        "symfony/routing": "5.1.*", // v5.1.11
        "symfony/twig-pack": "^1.0", // v1.0.1
        "symfony/var-dumper": "5.0.*", // v5.0.11
        "symfony/webpack-encore-bundle": "^1.7", // v1.8.0
        "symfony/yaml": "5.0.*" // v5.0.11
    "require-dev": {
        "symfony/maker-bundle": "^1.15", // v1.23.0
        "symfony/profiler-pack": "^1.0" // v1.0.5