If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeAt 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
.
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.
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!
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.
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."
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!
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
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!
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
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?
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!
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 ?
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!
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
// 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
}
}
sudo apt install php8.0-apcu
did it for me on Ubuntu 20.04In 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.