Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Configuring the Cache Service

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

At your terminal, get a list of all the services in the container matching the word "markdown" by running:

php bin/console debug:container markdown

Ah, recognize markdown.parser.light? That was what we used for our parser key! Select "1" and hit enter to get more info. No surprise: its class name is Light, which is the exact class that's being dump back in our browser, from our controller.

So, on a high level, by adding the parser config, we were basically telling the bundle that we want the "main" markdown parser service to be this one. In other words: when we autowire with MarkdownParserInterface, please give us markdown.parser.light.

Figuring out how to Configure the Cache

Anyways, one of our initial goals was to figure out how we could change the cache service to stop caching on the filesystem and instead cache somewhere else. In our controller, replace the dd() with dump($cache):

... lines 1 - 11
class QuestionController extends AbstractController
{
... lines 14 - 31
public function show($slug, MarkdownParserInterface $markdownParser, CacheInterface $cache)
{
... lines 34 - 44
dump($cache);
... lines 46 - 51
}
}

I'm using dump() so that the page still renders - it'll make things easier.

Now, move over, refresh and... interesting. The cache object is an instance of TraceableAdapter but inside it... ah, there's something called FilesystemAdapter. So that kind of proves that the cache is being stored somewhere on the filesystem.

Ok, so how can we control that? In reality... you'll probably just Google that to find what config you need. But let's see if we can figure this out ourselves. But, hmm, we don't really know which bundle this service comes from.

Open up config/bundles.php. When we started the project, the only bundle here was FrameworkBundle - the core Symfony bundle:

... lines 1 - 2
return [
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
... lines 5 - 12
];

Every other bundle was installed by us. And... since I don't really see any "CacheBundle", it's a good guess that the cache service comes from FrameworkBundle.

Let's test that theory! Find your terminal, pet your cat, and run:

php bin/console config:dump FrameworkBundle

Search this giant config for cache... I'm looking to see if there is maybe a cache section. Here it is! Under framework, this bundle has a sub-key called cache with quite a lot of example config. Because this is a bit hard to read, re-run this command with FrameworkBundle cache.

php bin/console config:dump FrameworkBundle cache

This only shows the cache section beneath framework.

So... this give us some nice information: we can see a key called app set to cache.adapter.filesystem... that kind of looks like something we might want to tweak... but I'm not sure... and I don't know what I would change it to.

So this is helpful... but not that helpful.

The debug:config Command

Another way that you can look at bundle configuration is to pass the exact same arguments to another command called debug:config:

php bin/console debug:config FrameworkBundle cache

The difference is subtle: config:dump shows you examples of all possible config whereas debug:config shows you your real, current values. Let's rerun this without the cache argument to see all our FrameworkBundle config:

php bin/console debug:config FrameworkBundle

Seeing our real values is cool... and we can see that under cache, the app key is set to cache.adapter.filesystem. But... we still don't really know what config we should change... or what to change it to!

Changing the Cache Adapter to APCu

Let's go see if the config file for this bundle can help. Logically, because we're configuring the framework key, open up config/packages/framework.yaml:

framework:
secret: '%env(APP_SECRET)%'
#csrf_protection: true
#http_method_override: true
# Enables session support. Note that the session will ONLY be started if you read or write from it.
# Remove or comment this section to explicitly disable session support.
session:
handler_id: null
cookie_secure: auto
cookie_samesite: lax
#esi: true
#fragments: true
php_errors:
log: true

Huh, I don't see a cache key! And it's possible that there is no cache key in our config and that the values we saw were the bundle's defaults. But actually, we do have some cache config... it's just hiding in its own file: cache.yaml. Inside, it has framework then cache:

framework:
cache:
# Unique name of your app: used to compute stable namespaces for cache keys.
#prefix_seed: your_vendor_name/app_name
# The "app" cache stores to the filesystem by default.
# The data in this cache should persist between deploys.
# 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
# Namespaced pools use the above "app" backend by default
#pools:
#my.dedicated.cache: null

It's not very common for a bundle's config to be separated into two files like this, but it is totally legal. Remember: the names of these files are not important at all. The cache config was separated because it's complicated enough to have its own file.

Anyways, this file is full of useful comments: it tells us how we could use Redis for cache or how we could use APCu, which is a simple in-memory cache. Let's use that: uncomment the cache.adapter.apcu line:

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

Before we even try that, find your terminal and run the debug:config command again:

php bin/console debug:config FrameworkBundle

Scroll up to the cache section: yes! This sees our new config! But... what difference does that make in our app? Find your browser, refresh, then hover over the target icon on the web debug toolbar to see the dump. This time the adapter object inside is ApcuAdapter! It's caching in memory! We made one little tweak and FrameworkBundle did all the heavy lifting to change the behavior of that service.

Oh, and if you get the error:

APCu is not enabled

It means you need to install the APCu extension. How you do that varies on each system but it's usually installed with pecl - like:

pecl install apcu

After you install it, make sure to restart your web server. You can do that by running

symfony server:stop

And then re-run the command to start the server:

symfony server:start

If installing this is causing you problems, don't worry about it. For example purposes, you can use the key cache.adapter.array instead. That's a service that actually does no caching, but it will allow you to see how the class changes.

Next, we've started to modify files in this config/packages/ directory. Now I want to talk more about the structure of this directory - specifically about Symfony environments, which will explain these dev/, prod/ and test/ sub-folders.

Leave a comment!

12
Login or Register to join the conversation
davidmintz Avatar
davidmintz Avatar davidmintz | posted 1 year ago

sudo apt install php8.0-apcu did it for me on Ubuntu 20.04

In any case, I would say knowing how to set up your development environment is a reasonable prerequisite for these tutorials. But even if you can't figure out how to enable APCu support, as the tutorial says, you can use the noop Array cache for now and move on.

1 Reply

Hey davidmintz

Thanks for sharing ubuntu solution for it! It may be helpful =)

Cheers!

Reply
Gediminas N. Avatar
Gediminas N. Avatar Gediminas N. | posted 2 years ago

When I uncomment "app: cache.adapter.apcu" in the cache.yaml file to enable cache service configuration I get this Symfony Exception - CacheException
APCu is not enabled.
I tried installing APCu into my php directory and it still doesnt have any effect.

This is the full error I get in terminal
"C:\xampp\htdocs\symfony\symfony-fundamentals-course-2>php bin/console config:debug cache
PHP Warning: PHP Startup: Unable to load dynamic library 'php_apcu.dll' (tried: C:\xampp\php\ext\php_apcu.dll (The
specified module could not be found.), C:\xampp\php\ext\php_php_apcu.dll.dll (The specified module could not be fo
und.)) in Unknown on line 0

Warning: PHP Startup: Unable to load dynamic library 'php_apcu.dll' (tried: C:\xampp\php\ext\php_apcu.dll (The spec
ified module could not be found.), C:\xampp\php\ext\php_php_apcu.dll.dll (The specified module could not be found.)
) in Unknown on line 0

In ApcuAdapter.php line 28:

APCu is not enabled."

1 Reply

Hey Gediminas N.

By looking the DLL name that it's trying to load php_php_apcu.dll.dll I think you wrote it wrong, it has the extension duplicated

Cheers!

Reply

Hello, I am blocked at the point of the course from yesterday with the same error. I tried everything I found here and on internet but nothing works. APCu is not enabled. I am on windows 10 , tried with php 7.3 and now I try with php 8 but nothing works. I use phpstorm
Please someone help me, I can continue the study :(

Or is not so important to stay on this problem?

--------------------------------

I found out that in App_KernelDevDebugContainerCompiler.log ==================>>>>>>>>>>>>>>> Symfony\Component\DependencyInjection\Compiler\RemoveAbstractDefinitionsPass: Removed service "cache.adapter.apcu"; reason: abstract.

---------------------UPDATE-------------------------------------
I have done! I downgraded Symfony to 5.0.11 and then install APCu as here

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

Reply

Hey zahariastefan462!

Ah, congrats on sorting this out! I'm not sure why you would need to downgrade to Symfony 5.0.11 (that may not have been necessary), but I'm super glad you got APCu installed. Keep up the good work!

Cheers!

Reply

Hello, thank you for reply! I choose to downgrade to 5.0.11 because I saw that the version of the course was made on 5.0.11 and the current one is a bit different and is complicate to understand the course for someone not experienced like me. (for example kernel.php is different written). When I try to understand or do like in the course doesn't work for all things, I got different errors).
For APCu downgrading symfony was the only solution that works for me. I tried for 2 entire days to solve this out in other ways but I didn't find any other solution. Thank you again! I appreciate

Reply
Jörg daniel F. Avatar
Jörg daniel F. Avatar Jörg daniel F. | posted 1 year ago

Hello I have the same error with APCu is not enabled.
I run this on a Mac OS X ver. 10.15.7
how I can fix this?
should I switch the php version or so?

Reply

Hey Jörg daniel F.!

Hmm. This can, annoyingly, be complex. The short answer is that you should be able to install it with pecl install pacu (you may need to sudo that, I can't remember). That should make everything work (though you'll need to restart your web server). However, if you have multiple versions of PHP on your machine, it's always possible something can go wonky.

If you're using the default Mac OS X PHP (that one that comes pre-installed with PHP), I'd highly recommend installing Homebrew, installing PHP through it, and then running "pecl install apcu".

Let me know if that helps - I have a Mac, and I happily use Homebrew :).

Cheers!

Reply
Yacine R. Avatar
Yacine R. Avatar Yacine R. | posted 2 years ago

Hello,

Same problem here that fUb had,

could you please make a tutorial about setting up PECL ? or give us an alternative way to set this kind of php extension up ?

I'm struggling with this part of the tutorial for more than 1 hour now,
and i'm still not able to find a proper tutorial on how to have this
working on php 7+ version, it seems that even if :

i pasted "extension=apcu.so" or "extension=php_apcu" in php.ini,
move the dll file into the ext folder of my current php version,
tried to do the same with the phpIniForApache file,

nothing worked out

basicaly the only thing that i'm actually doing is adding a new line on
the "server:start" return for the PHP-CGI, I have now more than 5 line
sayin

"Tailing PHP-CGI log file
(C:\Users\******\.symfony\log\39bd4f60ea1d574bf6b2c8b86a923cb74e6e5396\79ca75f9e90b4126a5955a33ea6a41ec5e854698.log)"

so i'm still stuck on the error frame with this info : "
Unaught Exception: APCu is not enabled.
{
"exception": {}
}
Uncaught PHP Exception
Symfony\Component\Cache\Exception\CacheException: "APCu is not enabled."
at
C:\wamp64\www\tuto\code-symfony-fundamentals\start\vendor\symfony\cache\Adapter\ApcuAdapter.php
line 28
{
"exception": {}
}
Could you please help me with this issue ?

Reply

Hey Yacine R.

The problem here is that the installation of APCu depends on the OS, so Ryan can't explain how to do it for all cases. If you're using PECL, I think what you need to do is this:


pecl channel-update pecl.php.net
pecl install apcu


And probably that's it but I'd suggest you to Google for it because I unknow your local machine settings

I hope it helps. Cheers!

Reply
Yacine R. Avatar

Hello Diego, thanks for your prompt reply

unfortunatly i'm on windows, so i cannot use directly "pecl" command, but in the end i manage to find my way out thanks to this link :
https://stackoverflow.com/questions/24448261/how-to-install-apcu-in-windows/42213575

2 Reply
Cat in space

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

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
    }
}