Buy
Buy
This tutorial has a new version, check it out!

Ok! Let's see if we can use this new service. First, some setup: in the template, remove the fun fact text and move it into GenusController by creating a new $funFact variable:

... lines 1 - 10
class GenusController extends Controller
{
/**
* @Route("/genus/{genusName}")
*/
public function showAction($genusName)
{
$funFact = 'Octopuses can change the color of their body in just *three-tenths* of a second!';
... lines 19 - 23
}
... lines 25 - 42
}

Let's make things interesting by adding some asterisks around three-tenths - Markdown should eventually turn that into italics.

Pass funFact into the template:

... 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!';
return $this->render('genus/show.html.twig', array(
'name' => $genusName,
'funFact' => $funFact,
));
}
... lines 25 - 42
}

And render it with the normal {{ funFact }}:

... lines 1 - 4
{% block body %}
... lines 6 - 7
<div class="sea-creature-container">
<div class="genus-photo"></div>
<div class="genus-details">
<dl class="genus-details-list">
... lines 12 - 15
<dt>Fun Fact:</dt>
<dd>{{ funFact }}</dd>
</dl>
</div>
</div>
<div id="js-notes-wrapper"></div>
{% endblock %}
... lines 23 - 40

When we refresh the browser, we have the exact same text, but with the unparsed asterisks.

Now, how the heck can we use the new markdown.parser service to turn those asterisks into italics?

Fetch the Service and Use it!

Remember: we have access to the container from inside a controller. Start with $funFact = $this->container->get('markdown.parser'). Now we have that parser object and can call a method on it. The one we want is ->transform() - pass that the string to parse:

... 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!';
$funFact = $this->container->get('markdown.parser')
->transform($funFact);
... lines 21 - 25
}
... lines 27 - 44
}

So.... how did I know this object has a transform() method? Well, a few ways. First, PhpStorm knows what the markdown.parser object is, so it gives me autocompletion. But you can always read the documentation of the bundle: it'll tell you how to use any services it gives us.

Ok team - time to try this out. Refresh! And hey, it's working! Ok, it's not exactly working. Open the page source: it looks like the parser is working its magic, but the HTML tags are being escaped into HTML entities.

This is Twig at work! One of the best features of Twig is that it automatically escapes any HTML that you render. That gives you free security from XSS attacks. And for those few times when you do want to print HTML, just add the |raw filter:

... lines 1 - 15
<dt>Fun Fact:</dt>
<dd>{{ funFact|raw }}</dd>
... lines 18 - 40

Refresh again: it's rending in some lovely italics.

Fetching Services the Lazy Way

One more thing! We can actually do all of this with less code. In the controller, replace $this->container->get() with just $this->get():

... 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!';
$funFact = $this->get('markdown.parser')
->transform($funFact);
... lines 21 - 25
}
... lines 27 - 44
}

This does the same thing as before.

Ok: here's the big, giant important takeaway so far: why do we add bundles to our app? Because bundles put more services in our container. And services are tools.

So my question now is: how can we configure these services so that they do exactly what we need them to?

Leave a comment!

  • 2017-10-23 Diego Aguiar

    Oh, it depends on the Symfony version you are using, I don't know when exactly they did that change (moving cache directory from app to var directory) but if you are using Symfony 3.* you need to adjust your symfony's plugin settings

  • 2017-10-20 Todd

    Soooo I had var/cache excluded from the beginning, per the recommendation in this course. However, when excluding var/cache PHP storm won't find any of my services. IF I cancel exclusion of that var/cache, now PHP Storm can find all my services and autocomplete works great...

    Are you guys sure about excluding that directory? I'm fairly certain appDevDebugProjectContainer.xml is important for mapping services.

    Or if you exclude var/cache maybe you need to manually map it?

    In this SO thread it seems to be an important file, but I don't have a cache directory in my app folder, only in var/cache, should I? Or is this something symfony changed recently?
    https://stackoverflow.com/q...

  • 2017-10-20 Todd

    Yeah, did that too. I've tried pretty much everything, but PHP storm can't seem to find any custom services I define.

  • 2017-10-20 Diego Aguiar

    Yeah, some times it gets glitched, try excluding from your project the folder `var/cache`

  • 2017-10-20 Todd

    Yeah, no exception so Symfony is finding it when things get executed, but PHP storm still says 'Missing service'. I've cleared the Symfony plugin index, invalidated the PHP storm caches.

    Using php storm 2017.2.1. It looks like others have had a similar issue, so maybe it will just start working, who knows..

  • 2017-10-20 Diego Aguiar

    Hey todd!

    When you do `$this->get('markdown.parsers');` does it throw an exception or something?
    If that's not the case and you are getting the correct object, it must be something related to PhpStorm settings, which version are you using? have you tried clearing the index? (inside settings->plugins->symfony)

  • 2017-10-19 todd

    markdown.parser seems to be having an issue getting recognized as a service and autocompleting for me. I have the symfony plugin and php annotations enabled for the project and autocomplete is working for other things.

    In $this->get( ), when I start typing 'markdown' it suggests 'templating.helper.markdown', but no other services will autocomplete, but it won't find markdown.parser.

    If I run ./bin/console debug:container markdown I see all the services which makes it even more confusing.

    ./bin/console debug:container markdown

    Select one of the following services to display its information:
    [0] markdown.parser.min
    [1] markdown.parser.light
    [2] markdown.parser.medium
    [3] markdown.parser.max
    [4] markdown.parser.flavored
    [5] markdown.parser.parser_manager
    [6] templating.helper.markdown
    [7] doctrine_cache.providers.my_markdown_cache
    [8] markdown.parser
    >

  • 2017-06-21 Yan Yong

    If you are getting transform method not implement error.
    Your composr download a dev version which does not have transform() method implemented.

    Do the following:
    1) Update composer.json under your project root directory
    "knplabs/knp-markdown-bundle": "^1.5",
    2) run update in your terminal
    composer update knplabs/knp-markdown-bundle

  • 2017-02-13 Blueblazer172

    yep :P that was the problem thanks :)

  • 2017-02-13 Victor Bocharsky

    Hey Hannes,

    I suppose you forget to pass funFact variable in GenusController::showAction(), which actually renders the `genus/show.html.twig` template ;)

    Cheers!

  • 2017-02-13 Blueblazer172

    when i want to add {{ funFact }} to the dd section in show.html.twig symfony throws this error: "Variable "funFact" does not exist in genus\show.html.twig at line 17"

    the fetNotesAction function looks like this:

    $funFact = 'Octopuses can change the color of their body in just *three-tenths* of a second!';

    $notes = [
    ['id' => 1, 'username' => 'AquaPelham', 'avatarUri' => '/images/leanna.jpeg', 'note' => 'Octopus asked me a riddle, outsmarted me', 'date' => 'Dec. 10, 2015'],
    ['id' => 2, 'username' => 'AquaWeaver', 'avatarUri' => '/images/ryan.jpeg', 'note' => 'I counted 8 legs... as they wrapped around me', 'date' => 'Dec. 1, 2015'],
    ['id' => 3, 'username' => 'AquaPelham', 'avatarUri' => '/images/leanna.jpeg', 'note' => 'Inked!', 'date' => 'Aug. 20, 2015'],
    ];
    $data = [
    'notes' => $notes,
    'funFact' => $funFact,
    ];

    return new JsonResponse($data);

  • 2017-02-08 Victor Bocharsky

    Hey Xeyos,

    Haha, I really wonder how you missed this installation ;)

    Cheers!

  • 2017-02-08 Xeyos

    I solved, i installed from https://github.com/KnpLabs/....
    I see now, i jumped the video 1 xd

  • 2017-02-08 Xeyos

    Hi, i have this error:
    "You have requested a non-existent service "markdown.parser". I check and in my services list markdown is not present.
    How can I add it?
    Thank you.

  • 2016-12-26 Victor Bocharsky

    Hey Kelvin,

    "$this->get()" in a controller is just a shortcut for "$this->container->get()". Open the Symfony\Bundle\FrameworkBundle\Controller\Controller::get() and you will see it yourself ;)

    Cheers!

  • 2016-12-24 kelvin atawura

    Is there an explanation behind why $this->container->get() is the same as $this->get()

  • 2016-12-15 Victor Bocharsky

    Great! Easy fix :)

  • 2016-12-14 Igor Kalamurda

    "Enable plugin for this project" - helps, Thanks!

  • 2016-12-14 Victor Bocharsky

    Hey Igor,

    Please, double check you have installed and *enabled* Symfony plugin in PhpStorm preferences for your project: press Command + , on Mac and type "Symfony" in search box. Then choose Languages and frameworks -> PHP -> Symfony and ensure you have checked all necessary boxes, especially the "Enable plugin for this project" one.
    After all, try to restart PhpStorm. Actually, it helps in most weird behaviors of PhpStorm :)

    P.S. Do you use the latest PhpStorm version?

    Cheers!

  • 2016-12-13 Igor Kalamurda

    Hello I also have a problem with autocompetion.
    1. I mark var/cache like excluded
    2. check for be sure class Symfony\Bundle\FrameworkBundle\Controller\Controller exist

    $funFact = $this->container->get('markdown.parser')
    when i write $this->container->(autocomplete show 'get' and other) then ->get( (here no autocomplete) )

  • 2016-12-08 Victor Bocharsky

    You're welcome! I'm glad we clarify it. And don't worry about this thread, it could help someone ;)

    Cheers!

  • 2016-12-08 Dainis Brjuhoveckis

    Sorry, my bad, I meant "markdown.parser", and it's working. The PHP Symphony auto suggest initially offered me only the "templating.helper.markdown" option for some reason so it confused me. Now it's working.

    Problem solved, thread can be deleted.

    Thank you :-)

  • 2016-12-08 Victor Bocharsky

    Oh, really? I can't find any mention about the "markdown.helper" in script code: https://github.com/knpunive... and even in the video of this chapter. Do you mean "markdown.parser"? Could you point me to the script/video where we use the "markdown.helper", please?

    Cheers!

  • 2016-12-08 Victor Bocharsky

    Hey Dainis,

    Why are you trying to inject "markdown.helper"? The "templating.helper.markdown" service looks like the correct one ;)

    Cheers!

  • 2016-04-21 Roy Hochstenbach

    The Synchronize option seems to be improving the auto-complete issues at some moments.

  • 2016-04-20 weaverryan

    Ah, interesting! Usually, when you say "extends Controller", it would offer you *both* choices - the one from HttpKernel\Tests and FrameworkBundle (since these are both called Controller). Obviously, you should use the one from FrameworkBundle. But if the one from FrameworkBundle isn't being offered as a choice, then it seems that PhpStorm doesn't see it at all (which is especially weird). Assuming the app works, then the problem is definitely with PhpStorm and you're doing good things by Invalidation the cache. I would also try to browser directly to the path - in vendor/symfony/symfony/src/Symfony/Bundle to see if the file is there. You can right-click on any directory and select "Synchronize" to (hopefully) make PhpStorm see the files in the directory (though Invalidating the Cache is similar).

    Let me know if you figure it out!

  • 2016-04-19 Roy Hochstenbach

    Thanks for your quick response ;-)

    I've tried marking the var/caches folder as Excluded, but the issue remains. I've also chosen the Invalidate Caches option, but that doesn't seem to have any effect.

    Also when i append 'extends Controller' next to a class statement, it automatically includes the file "Symfony\Component\HttpKernel\Tests\Controller" instead of "Symfony\Bundle\FrameworkBundle\Controller\Controller"

  • 2016-04-19 weaverryan

    Hi Roy!

    I think I know the problem. Also right-click on the var/cache directory and mark this as excluded. Before you did this, I bet that if you hovered over the word Controller (in extends Controller), you would have seen some message like "Multiple references found". The Controller class is cached in the var/cache directory (for performance), and this confuses PhpStorm and it quits auto-completing some things from Controller.

    Let me know if this was the problem! No auto-complete is no fun :)

  • 2016-04-19 Roy Hochstenbach

    For some reason PHPStorm is not autocompleting it properly. When I hover over $this->container, it shows me: "Field 'container' not found in GenusController". I have both the Symfony2 plugin and PHP Annotations plugin installed and enabled. Is there some sort of a 'magic switch' to get it to work? I've marked the 'src' directory as Sources Root.