This tutorial has a new version, check it out!

Using a Service

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

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!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=5.5.9",
        "symfony/symfony": "3.1.*", // v3.1.4
        "doctrine/orm": "^2.5", // v2.7.2
        "doctrine/doctrine-bundle": "^1.6", // 1.6.4
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
        "symfony/swiftmailer-bundle": "^2.3", // v2.3.11
        "symfony/monolog-bundle": "^2.8", // 2.11.1
        "symfony/polyfill-apcu": "^1.0", // v1.2.0
        "sensio/distribution-bundle": "^5.0", // v5.0.22
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "knplabs/knp-markdown-bundle": "^1.4" // 1.4.2
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.0.7
        "symfony/phpunit-bridge": "^3.0" // v3.1.3
    }
}