Buy

We have a new toy, I mean service! In GenusController, let's use it: $cache = $this->get('') and start typing markdown. Ah, there's our service!

55 lines src/AppBundle/Controller/GenusController.php
... lines 1 - 10
class GenusController extends Controller
{
... lines 13 - 15
public function showAction($genusName)
{
$funFact = 'Octopuses can change the color of their body in just *three-tenths* of a second!';
$cache = $this->get('doctrine_cache.providers.my_markdown_cache');
... lines 21 - 34
}
... lines 36 - 53
}

Here's the goal: make sure the same string doesn't get parsed twice through markdown. To do that, create a $key = md5($funFact);:

55 lines src/AppBundle/Controller/GenusController.php
... lines 1 - 19
$cache = $this->get('doctrine_cache.providers.my_markdown_cache');
$key = md5($funFact);
... lines 22 - 55

To use the cache service, add if ($cache->contains($key)). In this case, just set $funFact = $cache->fetch($key);:

55 lines src/AppBundle/Controller/GenusController.php
... lines 1 - 19
$cache = $this->get('doctrine_cache.providers.my_markdown_cache');
$key = md5($funFact);
if ($cache->contains($key)) {
$funFact = $cache->fetch($key);
... lines 24 - 28
}
... lines 30 - 55

Else, we're going to need to parse through Markdown.

Let's live dangerously: add a sleep(1); to pretend like our markdown transformation is really taking a long time. Next, parse the fun fact and finish with $cache->save($key, $funFact):

55 lines src/AppBundle/Controller/GenusController.php
... lines 1 - 21
if ($cache->contains($key)) {
$funFact = $cache->fetch($key);
} else {
sleep(1); // fake how slow this could be
$funFact = $this->get('markdown.parser')
->transform($funFact);
$cache->save($key, $funFact);
}
... lines 30 - 55

Let's do this! Go back to the browser... and watch closely my friends. Refresh! Things are moving a bit slow. Yep: the web debug toolbar shows us 1048 ms. Refresh again. super fast! Just 41 ms: the cache is working! But... uhh... where is this being cached exactly?

Out of the box, the answer is in var/cache. In the terminal, ls var/cache, then ls var/cache/dev:

ls var/cache/dev/

Hey! There's a doctrine directory with cache/file_system inside. There is our cached markdown.

This bundle assumed that this is where we want to cache things. That was really convenient, but clearly, there needs to be a way to control that as well.

Configuring the Cache Path

Rerun config:dump-reference doctrine_cache:

./bin/console config:dump-reference doctrine_cache

Ah, there's a directory key we can use to control things. In the editor, add this new directory key and set it to /tmp/doctrine_cache for now:

78 lines app/config/config.yml
... lines 1 - 72
doctrine_cache:
providers:
my_markdown_cache:
type: file_system
directory: /tmp/doctrine_cache

Ok, back to the browser team. Refresh! Poseidon's beard, check out that HUGE error! "Unrecognized option 'directory'". Remember, configuration is validated... which means we just messed something up. Oh yea: I see the problem: I need to have file_system and then directory below that. Add file_system above directory and then indent it to make things match:

79 lines app/config/config.yml
... lines 1 - 72
doctrine_cache:
providers:
my_markdown_cache:
type: file_system
file_system:
directory: /tmp/doctrine_cache

Ok, try this out one more time.

It should be slow the first time... yes! And then super fast the second time. In the terminal, we can even see a /tmp/doctrine_cache/ directory:

ls /tmp/doctrine_cache/

Big picture time: bundles give you services, and those services can be controlled in config.yml. Every bundle works a little bit different - but if you understand this basic concept, you're on your way.

Leave a comment!

  • 2016-11-04 weaverryan

    Hey Noby!

    Yes and no :). A lot of the work we did was initial setup. So if you wanted to cache in a different route/controller, you wouldn't need to do much work at all: (A) add a new entry in config.yml under "doctrine_cache" and "providers" then (B) fetch that service in a controller and use it to cache. Not too much work.

    But also, you likely won't need to cache very often. Of course, it depends on your application, but, for example, the vast majority of the routes/controllers on our site don't have any caching: it's just fast enough.

    Cheers!

  • 2016-11-04 Nobuyuki Fujioka

    Hi,
    Ok, a bit complicated. but, it is working now.
    Do I have to do this process for every route page/function to have cache working?

    Kind regards,
    Noby

  • 2016-10-12 Victor Bocharsky

    Hey Marco,

    Something wrong with the "markdown.parser" service definition in services.yml - please, double check its spelling and try to clear the cache. If it doesn't help you - please, show your "markdown.parser" service definition here.

    Cheers!

  • 2016-10-12 Marco Koopman

    Hey I've fixed the typo but now it says You have requested a non-existent service "markdown.parser"

  • 2016-10-11 diego82

    Yep! "sometimes people will open a directory that contains many projects, and this can confuse PhpStorm"

  • 2016-09-29 Victor Bocharsky

    Yo Marco,

    I bet I know the problem. You made a type in this service name: it should be "markdown.parser" instead of "markdown.paser" ;)

    Cheers!

  • 2016-09-29 Marco

    Hey! I get the error: You have requested a non-existent service "markdown.paser". Ive done everything in the video I dont know what is wrong please help :)

  • 2016-09-27 Maksym Minenko

    Yes, it does. It seems like I had have quite a vague notion about Twig cache files.

    And now I also understand why some people think Twig is too heavy. :)

  • 2016-09-26 weaverryan

    Yo Maksym!

    Great question :). You're right that the Twig templates are cached to PHP files. But, the *output* of the templates is not cached. What I mean is: the Twig language is parsed and a PHP file is built in the cache. This cache is just a translation of the Twig language into the PHP language. If you looked at the cached Twig file (which you can do by browsing in var/cache/dev/twig), you'll find that it includes echo statements for variables that will be passed in at runtime. This cached file is used to render different content based on the different variables that you pass into it.

    This also means that your controller code is *always* executed (since it needs to prepare the variables for the Twig template). And in this case, your controller code is actually the code that will be slow (as it parses the markdown). That's why we add that caching layer.

    Does that make sense? There *are* of course ways to cache the *output* of your page (what you'd normally think of as some sort of "page caching"). We don't have a tutorial on this yet, but it's one of the coolest features of Symfony: http://symfony.com/doc/current...

    Cheers!

  • 2016-09-26 Maksym Minenko

    But Twig caches its templates, doesn't it? So, do we really need another cache for markdown service?

  • 2016-09-12 Victor Bocharsky

    Ah, good catch! For Windows users it makes sense since windows has a bit different file system, so it doesn't have "/tmp/" dir as Mac/Linux does. Probably, you could use C:\Users\<username>\AppData\Local\Temp instead, but I'd recommend to use the local Symfony cache dir, i.e. "%kernel.root_dir%/cache/doctrine_cache" rather.

    Cheers!

  • 2016-09-09 Krzysztof

    I'm using Windows and I had a similar problem. I thought directory tmp/doctrine_cache didn't exist but it did, just in other location.
    It should be created in d:/xampp/htdocs/my_project/ but instead I found it directly in d:/. I don't know why. I googled it and I found I can use %kernel.root_dir%, so I changed my configuration from:

    directory: /tmp/doctrine_cache

    to

    directory: %kernel.root_dir%/../tmp/doctrine_cache

    and it worked.

    Later I found out that these "kernel" parameters are described in next chapters of this course, :)

  • 2016-08-05 Victor Bocharsky

    Hey 3amprogrammer ,

    You're right, Doctrine relates to the database, but also it relates to the data in common. Doctrine has a nice doctrine/cache library which helps to cache data, i.e. you could easily cache data which you fetch from a database, which in turn reduce a database server loading.

    Cheers!

  • 2016-08-05 3amprogrammer

    I have a silly question. Why caching markdown has anything to do with doctrine? I tough doctrine is related to database? That confuses me a bit.

  • 2016-08-01 Victor Bocharsky

    Hey dankinchen ,

    If folder never appear after it was deleted - probably you have permission problem. To check it - use `ls -la` command.

    Yes, you're right. The "Project" mode do not show you excluded directories. Excluded files are ignored by PhpStorm while searching, parsing, watching etc.

    Cheers!

  • 2016-07-31 dankinchen

    I cannot get cache to work for me either. There were files in there but when I deleted the doctrine directory it never came back. I mapped $key to twig and dumped it and sure enough there was an md5 hash in there. You know another thing I cannot navigate to "dir var/cache/" I can only see the contents of var. When I switch between project files and project I get different content? Is this because in an earlier video you had us all exclude cache directory in phpstorm?

  • 2016-07-29 Nathaniel Kolenberg

    Thanks for getting back to me. After deleting the directory and refreshing, it seemed to work :)

    Thanks a lot!

  • 2016-07-25 weaverryan

    Hi Nathaniel!

    Ah, thanks for the nice words! I'm very happy about this :).

    About your question, I have a few ideas:

    1) Obviously, make sure that you configure the "directory" key in config.yml set to /tmp/doctrine_cache. You said you followed word-for-word - but this was the most obvious thing to check, so let's start there!

    2) If you delete the var/cache/dev/doctrine... directory and then refresh, is it re-created? Or does this directory just remain because we were using it earlier?

    It's possible that there's some weird bug in the tutorial - I'm happy to help you dig into what's going on :).

    Cheers!

  • 2016-07-22 Nathaniel Kolenberg

    Hi weaverryan! Your tutorials are excellent w.r.t. Symfony! I just have one quick question regarding this one though. After coding along word for word, I find that the last directory: tmp/doctrine_cache doesn't exist for me when I try to ls into it, whereas the var/cache/dev/doctrine./cache/file_system/60 does exist. Any suggestion as to why this could be?
    Thanks in advance!

  • 2016-06-18 weaverryan

    Hey Karlola!

    Hmm, let's see if we can figure this out. First, *after* this chapter, we start getting fancier and only configuring the cache to work on one environment versus another. So, make sure that you don't have any of that code yet - else the cause could be something entirely different :).

    If you're seeing no files, then we know that the cache isn't actually saving. In GenusController, make sure you have the $cache->save($key, $funFact); line in there. I might also var_dump($key); to make sure this is a real value (if, for some crazy reason this is a blank value, it might not be able to cache).

    Let me know what you find out! Definitely focus on why the cache is not *saving*.

    Cheers!

  • 2016-06-16 Karlola

    I've been coding along word-for-word, yet something is messed up with my caching: both the long path `var/cache/dev/doctrine/cache/file_system/` and our custom path `/tmp/doctrine_cache` contain no files or subfolders. The site loads with no explicit errors but also keeps sleeping for the ordered 1 second with every refresh. Where should I look for hints?

  • 2016-06-14 weaverryan

    Cheers! And yea, I think Doctrine is much harder than Symfony :). Doctrine gets tricky with relationships, and it really just comes down to getting the configuration correct, then everything works nicely. Doctrine is also more "work" (more writing code) than something like Propel - another reason you sometimes hear bad things about it :).

    Keep up the good work!

  • 2016-06-14 JLChafardet

    Yeah, I'm 100%(notreally) new to "Symfony" and Doctrine, I mean, not really that new to symfony itself, as I've been using a custom implementation of Silex from a friend for about 2 years, the learning curve into symfony, thats supposedly step, is not being so much as I expected it, surely because of my Silex experience.

    Doctrine on the other hand, its a whole new world for me, as the Silex implementation that I've been using was based on propel1 (yes propel1 not propel2), and well I was worried that using Dogtrine*cough* was going to be a really tough act, but seeing how it works, is just neat, its still a bit black-magic-ish, but it matters not, just been reading about it for a day and half haha.

    again Thanks for taking the time to reply.

  • 2016-06-14 weaverryan

    Haha, yep - you totally answered your own question :). But to add some more, there end up being 3 possibilities (at least):

    1) Add a different doctrine_cache in config.yml, config_dev.yml, config_prod.yml, etc, with different directories
    2) Only configure in config.yml, but set the directory to something that includes `%kernel.environment%` - that's the environment name. Or, `%kernel.cache_dir%` - which is the path to the cache directory, which already differs by environment
    3) Only configure in config.yml, but set directory to a parameter - like `%my_cache_dir%`. Then, set `my_cache_dir` under the parameters key in the other files (you could set a default in config.yml, then override in other config files).

    The big thing is to understand how the config files load each other (which you clearly do!). Then, you start to see a lot of possibilities :).

    Cheers!

  • 2016-06-13 JLChafardet

    ok, so here I'm guessing, if i want to have cache for dev in one place, and cache for prod in another (just for the heck of it, lets just go with the argument of wanting to have ALOT of cache because i run dev, test, prod on the same directory, bleh bleh haha)

    I would need to configure the cache (doctrine_cache) on config_prod/test/dev.yml ? and assign it whatever folder i want (lets just say .var/cache/{env}

    where {env} is the environment (prod/test/dev) and it should work?

    checking the conf files, i see test imports dev, whereas prod imports config.yml

    so yes theoretically speaking it should work. ha! answering my question on the same question, isnt this quite nice!

  • 2016-06-03 weaverryan

    Hey Mike!

    Ah, so you get auto-completion at all when you try to reference the services? I'm not sure what else to try either :/. Is your PhpStorm project opened just to *one* Symfony project (sometimes people will open a directory that contains many projects, and this can confuse PhpStorm). Are you also on the latest versions of PhpStorm and the plugin? I'm just trying to think of possible reasons for this :).

    Cheers!

  • 2016-06-02 Mike

    Thanks for the info.

    I tried what you said, but it still doesn't find the doctrine_cache.providers.my_markdown_cache when I start typing markdown. It did however remove all of the markdown.parser.max and markdown.parser.min options. Not really sure what else to try.

  • 2016-05-31 weaverryan

    Hey Mike!

    Yes, please do piggyback - I'd love if we could figure this out for everyone :).

    So, you *are* seeing auto-completion on service ids, so that's the first thing to note. I think some people don't get auto-completion at all. And you *are* seeing a lot of valid services in your auto-completion - like markdown.parser.max (that's a real service that *should* auto-complete). The question just is, why aren't you seeing the new doctrine_cache... service?

    One way or another, the likely cause is either that (A) your Symfony cache is out of date (fixing that is as simple as running the bin/console debug:container that we ran in the previous chapter) or (B) PhpStorm didn't see the update. From what I know, phpstorm uses a few strategies to know what your services are: it parses your YAML/XML files, but it also looks (I believe) at a dump container metadata file in your var/cache/dev directory. When you first load a page / run bin/console after making the config changes, that new file is dumped. PhpStorm may not be seeing this for some reason. Related to this, in the PhpStorm settings, under the Symfony plugin, there is a section called "Container". Here, you can actually manually point PhpStsorm at this dumped, XML file (it's called var/cache/dev/appDevDebugProjectContainer.xml). I've never had to do this, but perhaps it would make a difference?

    This particular example is a little different overall, because we aren't configuring this service directly in one of our YAML files. So, PhpStorm relies on that dumped XML file - again, afaik - whereas normally it would also be parsing our YAML files to find our services.

    I hope this helps - let me know if you find anything out!

  • 2016-05-27 Mike

    Hi - If I can just piggyback off of this question. I am also having the same problem. I have the plugin installed and enabled. When I watch your tutorials (which are great by the way!) my autocomplete never really looks the same as yours. For this exact example when I type markdown i see stuff like markdown.parser, markdown.parser.max, markdown.parser.min, etc. even if I try typing in doctrine_cache it does not autocomplete. Any ideas why?

  • 2016-05-18 weaverryan

    I do have the Symfony plugin for PhpStorm, but I'm guessing you have this? If you do have this, make sure it's enabled for your project: http://knpuniversity.com/scree...

    This plugin is the one that gives you this auto-complete.

  • 2016-05-15 Konrad ZajÄ…c

    Hi,
    I'm finding out I don't have the autocompletions you have i.e. the doctrine_cache.providers.my_markdown_cache
    Do you have any special plugins?