Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
This tutorial has a new version, check it out!

debug:container & Cache Config

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $10.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

I want to talk more about this key: markdown.parser.light:

knp_markdown:
parser:
service: markdown.parser.light

We got this from the documentation: it told us that there are five different valid values that we can put for the service key.

But, this is more than just a random config key that the bundle author dreamt up. Remember: all services live inside an object called the container. And each has an internal name, or id.

It's not really important, but it turns out that markdown.parser.light is the id of a service in the container! Yep, with this config, we're telling the bundle that when we ask for the Markdown parser - like we are in the controller - it should now pass us the service that has this id.

Go to your terminal and run:

./bin/console debug:autowiring

And scroll to the top. Check this out! The MarkdownInterface is now an alias to markdown.parser.light! Before the config change, this was markdown.parser.max. Yep, this literally means that when we use MarkdownInterface, Symfony will pass us a service whose id is markdown.parser.light.

Normally, you do not need to worry about all of this. I mean, if you just want to use this bundle and configure a few things, follow its docs, make some config tweaks, go on a space walk, and then keep going!

The Many other Services in the Container

But we're on a quest to really understand how things work! Here's the truth, this is not a full list of all of the services in the container. Nope, not even close. This time, run:

./bin/console debug:container --show-private

This is actually the full list of the many services in the container. The service id is on the left, and the class for that object is on the right. Don't worry about the --show-private flag: that just makes sure this lists everything.

But, in reality, most of these services are internal, boring objects that you'll never use. The most important services show up in debug:autowiring and are really easy to access.

But yea... you can also fetch and use any of these services, and sometimes you'll need to. I'll show you how a bit later.

But here are the two big takeaways:

  1. There are many services in the container and each has an id.
  2. The services you'll use 99% of the time show up in debug:autowiring and are easy to access.

Configuring the Cache Object

Let's play with one more object. Instead of dumping $markdown, dump the $cache object:

... lines 1 - 13
class ArticleController extends AbstractController
{
... lines 16 - 26
public function show($slug, MarkdownInterface $markdown, AdapterInterface $cache)
{
... lines 29 - 53
dump($cache);die;
... lines 55 - 67
}
... lines 69 - 80
}

Find your page and refresh! Interesting: it's something called a TraceableAdapter, and, inside, a FilesystemAdapter!

So I guess our cache is being saved to the filesystem... and we can even see where in var/cache/dev/pools.

So... how can we configure the cache service? Of course, the easiest answer is just to Google its docs. But, we don't even need to do that! The cache service is provided by the FrameworkBundle, which is the one bundle that came automatically with our app.

Debugging your Current Config

Tip

In a recent change to the recipe, the cache config now lives in its own file config/packages/cache.yaml

Open framework.yaml and scroll down:

framework:
... lines 2 - 16
cache:
# Put the unique name of your app here: the prefix seed
# is used to compute stable namespaces for cache keys.
#prefix_seed: your_vendor_name/app_name
# The app cache caches to the filesystem by default.
# Other options include:
# Redis
#app: cache.adapter.redis
#default_redis_provider: redis://localhost
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
#app: cache.adapter.apcu

Hey! This file even comes with documentation about how to configure the cache! Of course, to get an even bigger example, we can run:

./bin/console config:dump framework

Here's the cache section, with some docs about the different keys. Now, try a slightly different command:

./bin/console debug:config framework

Instead of dumping example config, this is our current config! Under cache, there are 6 configured keys. But, you won't see all of these in framework.yaml: these are the bundle's default values. And yea! You can see that this app key is set to cache.adapter.filesystem.

Changing to an APCu Cache

The docs in framework.yaml tell us that, yep, if we want to change the cache system, app is the key we want. Let's uncomment the last one to set app to use APCu: an in-memory cache that's not as awesome as Redis, but easier to install:

framework:
... lines 2 - 16
cache:
... lines 18 - 28
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
app: cache.adapter.apcu

And just like with markdown, cache.adapter.apcu is a service that already exists in the container.

Ok, go back and refresh! Yes! The cache is now using an APCuAdapter internally!

Tip

Fun fact! Running ./bin/console cache:clear clears Symfony's internal cache that helps your app run. But, it purposely does not clear anything that you store in cache. If you want to clear that, run ./bin/console cache:pool:clear cache.app.

Bundle Config: the Good & Bad

So the great thing about configuring bundles is that you can make powerful changes with very simple config tweaks. You can also dump your config and Symfony will give you a great error if you have any typos.

The downside about configuring bundles is that... you really need to rely on the debug tools and documentation. I mean, there's no way we could sit here long enough and eventually figure out that the cache system is configured under framework, cache, app: the config structure is totally invented by the bundle.

Let's go back to our controller and remove that dump:

... lines 1 - 13
class ArticleController extends AbstractController
{
... lines 16 - 26
public function show($slug, MarkdownInterface $markdown, AdapterInterface $cache)
{
... lines 29 - 53
dump($cache);die;
... lines 55 - 67
}
... lines 69 - 80
}

Make sure everything still works. Perfect! If you get an error, make sure to install the APCu PHP extension.

Next, let's explore Symfony environments and totally demystify the purpose of each file in config/.

Leave a comment!

39
Login or Register to join the conversation
Mikhail G. Avatar
Mikhail G. Avatar Mikhail G. | posted 3 years ago

Hi guys!
I didn't found an answer here how to install APCu on Mac so I want to write my own instruction.

So first you need to have a brew.

If you have PECL, you can go to the next step; if not, you should update PHP
brew install php

Then you should install APCu with PECL
pecl install apcu

After that open your php.ini and add these line to the end of file

[apcu]
extension=php_apcu.dll
apc.enabled=1
apc.shm_size=32M
apc.ttl=7200
apc.enable_cli=1
apc.serializer=php

Tadaaaaam! 🎉
Everything works as expected 💪🏻

1 Reply

Awesome! Thanks for sharing it Mikhail G.

Reply
Abelardo Avatar
Abelardo Avatar Abelardo | posted 3 years ago

Hi everyone,
In order to install APCu inside Linux, you must run:


$ sudo apt-get install php-apcu

Best regards

1 Reply
Allison R. Avatar

Or

$ sudo yum install php-pecl-apcu

And don't forget to restart the web server

1 Reply

Hey Alar

Thank you for this tip when you have Yum package manager instead of Apt!

Cheers!

Reply

Hey Abelardo,

Thank you for sharing this with others!

Cheers!

1 Reply
Mike P. Avatar
Mike P. Avatar Mike P. | posted 4 years ago

Speaking about performance, do you recommend to install the PECL YAML PHP Extension? Ive heard that it can parse up to 5x faster .YAML files than symfony itself.

1 Reply

Hey Mike P.!

Ah, VERY good question & point! First, if you did install the YAML PECL extension, it wouldn't make any difference: internally, Symfony always uses its own parser (it isn't written to fallback to the PECL version if it's available). But, more importantly, YAML is ONLY parsed when the container is being built. And this happens only in 2 different scenarios:

1) During development, the container is rebuilt (and YAML is parsed) when refreshing after you've made some changes to your configuration files. So, it's not parsed on every request - only when needed.

2) On production, the container is rebuilt only ONE time, during your deploy phase, when you run the bin/console cache:warmup command. Then, your YAML files are NEVER parsed again (you could even delete them!).

So, the YAML parsing adds limited overhead during development and zero overhead during production. And even in development, I think you'd find that it is very little of your processing time (I've never benchmarked this, but I DO know that the code that takes up most of the time is PHP code that's independent of the YAML parsing).

tl;dr You can't install the PECL extension to speed things up... but you also don't need to even worry about it ;).

Cheers!

1 Reply
Mike P. Avatar

You are brilliant! Thanks

Reply
Default user avatar

Hello Ryan, any reference to configure the app.cache using a redis cluster? Can I pass a snc_redis config as parameter?

1 Reply

Hey @rafix,

To configure app.cache to use Redis you need to tweak the config to:


framework:
cache:
app: cache.adapter.redis
default_redis_provider: "redis://localhost"

Here's some docs about RedisAdaper: http://symfony.com/doc/3.4/...

> Can I pass a snc_redis config as parameter?
Unfortunately no, as far as I see from its configuration. You can check it with "bin/console config:dump framework", looks for the "cache" key.

FYI, here's related issue: https://github.com/snc/SncR...

Cheers!

2 Reply

Hello :)
How can I use different cache adaptors in different scenarios? for example somewhere I prefer to use redis and somewhere else apcu? the only way is by creating custom pools or is there another options?

Reply

Hey Amin,

Yeah, you just need to create different cache pools. Then, Symfony will automatically register them for autowiring, see those new services in "bin/console debug:autowire" to know how to get them

Cheers!

Reply
Lionel E. Avatar
Lionel E. Avatar Lionel E. | posted 3 years ago

Just installed APCU on windows, am I missing something or APCU is really slower than filesystem cache ?

Reply

Hey Lionel,

Well, it should not, but it relates to Windows OS probably :/ Looks like for you it's slower than filesystem cache, that's weird. Could you restart your computer and try again? I'd also recommend you to turn off your antivirus if it's possible, it may block/check requests and that's why it slows. Otherwise, I'd recommend you to try a different cache storage like Redis maybe if it's an option for you? Unfortunately, things might be tricky on Windows :/

Cheers!

Reply
Dirk Avatar

Perhaps a silly question, but I don't fully understand when you want to clear Symfony's internal cache. Should you do this just once when you deploy your application? Or should you do it (also) every time you make changes to your application's code (a change to a controller or a twig-file for example)?

Reply

Hey Dirk

On production you have to clear the cache after doing almost any change, by running bin/console cache:clear
but if you are on "dev" environment you don't have to manually run that command, Symfony is very smart at detecting when to clear the cache but sometimes you have to manually clear the "var/cache" folder, it's a rare situation but sometimes you have to do it.

Cheers!

Reply

Hello,
For information : Cache config is in the cache.yaml file (and no longer in the framework.yaml file).

Reply

Hey ojtouch!

You're right! For clarity, in new projects, the cache config now lives in config/packages/cache.yaml. We'll add a note to the tutorial to make sure other people don't get confused!

Thanks!

Reply
Default user avatar
Default user avatar Mathieu Jourdan | weaverryan | posted 3 years ago

Does it mean that you only need to uncomment the "app: cache.adapter.apcu" line in cache.yaml ?
... cause, by doing all the previous setup, i got a CacheException alert telling me that APCu in not enabled

Reply

Hey Mathieu,

Sure, since you uncomment APCu cache adapter - you should have it installed and enabled so you can use it in your application. And that's great that you got a clear error message for it.

Cheers!

Reply
Sarah V. Avatar
Sarah V. Avatar Sarah V. | posted 4 years ago

Hi guys, I have read all the comments but I can't seem to figure out how to enable the APCu when using the built in server of Symfony? Is this the moment I stop using the built in server and configure my own apache and php?

Reply

Hey Sarah V.

You should be able to enable APCu even for the Symfony's built-in web server but you have to install & enable it first on your computer. Probably this guide will help you: https://serverpilot.io/docs...

Cheers!

1 Reply
Sarah V. Avatar

You're the best <3

Reply
Abelardo L. Avatar
Abelardo L. Avatar Abelardo L. | posted 4 years ago

Hi everyone,

If apcu is not installed onto your system...

https://stackoverflow.com/q...

Brs.

Reply

Hey Abelardo L.

Thanks for the info man!

1 Reply
Mike P. Avatar
Mike P. Avatar Mike P. | posted 4 years ago

Is APCu recommended for most projects (instead of choosing nothing)?
I have read on the internet: "All PHP packages now come pre-built with Zend OPcache by default, but you can still install APCu Cache as a data store." so does symfony performance improve with APCu instead of the default Zend OPcache?

Reply

Hey Mike,

Good question. APCu and OPcache are different things, as also APCu and APC are different things as well, because APCu is a *user* cache. If we're talking about legacy projects that does not have OPcache, then installing APC will improve performance, but if your PHP version already have OPcache - you don't need neither APC nor APCu, OPcache is enought. However, APCu can be used for cache other things, but it require some configuration.

Btw, this article may be interesting for you: https://symfony.com/doc/cur...

Cheers!

1 Reply
Luis M. Avatar
Luis M. Avatar Luis M. | posted 4 years ago

It would be nice to have a docker-compose installation in order to don't have to install APCu locally or struggle with its installation.

Reply

Hey Luis,

Yes, agree, that would be cool, but it would be harder to maintain this code for us. And to be honest, Docker deserves a separate topic and not all our users may know and use this technology.

Cheers!

1 Reply
Ajie62 Avatar

Hello,

I tried to code along but got stuck when I activated APCu in framework.yaml. When I refreshed the page, I got a CacheException and the following message: "APCu is not enabled". Of course, I watched the video in its entirety and know that I have to download the APCu PHP extension but after looking for a solution to do so, the only resource I found was this website: https://guides.wp-bullet.co... It concerns Wordpress, so I was wondering it this method is a good way to install APCu within the scope of this course, or do you suggest me another way?

Thanks.

Reply
Default user avatar

For those on Ubuntu 16.04 (or probably other Debian flavors) and using PHP 7.2, I ran the console command:


sudo apt-get install php7.2-opcache php-apcu

I then had to restart my server to get it to kick in:


./bin/console server:stop
./bin/console server:run
2 Reply

Hey Chris,

Thanks for sharing it! Anyway, after successful installation of new PHP extensions just do not forget to restart your web server. And btw, you also need to restart PHP-FPM if you use a real web server like Nginx or Apache along with PHP-FPM.

Cheers!

1 Reply

Hey Ajie62

If you managed to install APCu, maybe you just need to enable it, you have to add "extension=apcu.so" to your php.ini file (if you are on Windows I believe it should be "extension=apcu.dll", after that, restart your web server and everything should be ok.

Cheers!

Reply
Ajie62 Avatar
Ajie62 Avatar Ajie62 | MolloKhan | posted 4 years ago | edited

Hi MolloKhan

Unfortunately, I didn't even manage to install APCu. I'm on a Macbook Air.

Reply

Oh, well, I more a linux/windows user, but I just found a post that may guide you in the right direction. Open this link: https://getgrav.org/blog/ma... and scroll down to the section "Install OPcache and APCu"

I hope it helps you. Cheers!

1 Reply

Hi,

I'm struggling to install APCu PHP extension on Windows. How should it be done?

Reply

Hey Daniel,

Great! And thanks for sharing it with other Windows users!

Cheers!

Reply
Cat in space

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

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.1.3",
        "ext-iconv": "*",
        "knplabs/knp-markdown-bundle": "^1.7", // 1.7.0
        "nexylan/slack-bundle": "^2.0,<2.2.0", // v2.0.0
        "php-http/guzzle6-adapter": "^1.1", // v1.1.1
        "sensio/framework-extra-bundle": "^5.1", // v5.1.4
        "symfony/asset": "^4.0", // v4.0.4
        "symfony/console": "^4.0", // v4.0.14
        "symfony/flex": "^1.0", // v1.17.6
        "symfony/framework-bundle": "^4.0", // v4.0.14
        "symfony/lts": "^4@dev", // dev-master
        "symfony/twig-bundle": "^4.0", // v4.0.4
        "symfony/web-server-bundle": "^4.0", // v4.0.4
        "symfony/yaml": "^4.0" // v4.0.14
    },
    "require-dev": {
        "easycorp/easy-log-handler": "^1.0.2", // v1.0.4
        "symfony/debug-bundle": "^3.3|^4.0", // v4.0.4
        "symfony/dotenv": "^4.0", // v4.0.14
        "symfony/maker-bundle": "^1.0", // v1.0.2
        "symfony/monolog-bundle": "^3.0", // v3.1.2
        "symfony/phpunit-bridge": "^3.3|^4.0", // v4.0.4
        "symfony/profiler-pack": "^1.0", // v1.0.3
        "symfony/var-dumper": "^3.3|^4.0" // v4.0.4
    }
}