Tagging Services (and having Fun!)
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.
We need to somehow tell Twig about our fun new Twig extension. To do that, first,
register it as a service. The name doesn't matter, so how about app.markdown_extension
.
Set the class, but skip arguments
: we don't have any yet, so this is optional:
// ... lines 1 - 5 | |
services: | |
// ... lines 7 - 10 | |
app.markdown_extension: | |
class: AppBundle\Twig\MarkdownExtension | |
// ... lines 13 - 15 |
Now, this service is a bit different: it's not something that we intend to use
directly in our controller, like app.markdown_transformer
. Instead, we simply
want Twig to know about our service. We somehow need to raise our hand and say:
Oh, oh oh! This service is special - this service is a Twig Extension!
We do that by adding a tag. The syntax is weird, so stay with me: Add tags:
,
then under that a dash and a set of curly-braces. Inside, set name
to twig.extension
:
// ... lines 1 - 5 | |
services: | |
// ... lines 7 - 10 | |
app.markdown_extension: | |
class: AppBundle\Twig\MarkdownExtension | |
tags: | |
- { name: twig.extension } |
And that's it.
Real quick - make sure it works. Refresh! Boom! We see a pretty awesome-looking upper-case string.
What are these Tags???
Tags are the way to hook your services into different parts of the core system.
When Symfony creates the twig
service, it looks for all services in the container
that are tagged with twig.extension
. It then configures these as extensions on
twig
.
Google for "Symfony dependency injection tags": there's an awesome reference section on Symfony.com called The Dependency Injection Tags. It lists every tag that can be used to hook into core Symfony. And if you're tagging a service, well, you're probably doing something really cool.
For example, if you want to register an event listener and actually hook into Symfony's
boot process, you create a service and then tag it with kernel.event_listener
.
You won't memorize all of these: you just need to understand their purpose. Someday,
you'll read some docs or watch a tutorial here that will tell you to tag a service.
I want you to understand what that tag is actually doing.
Finish the Extension
Let's finish our extension: we need to parse this through markdown. We find ourselves
in a familiar position: we're inside a service and need access to some other service:
MarkdownTransformer
. Dependency injection!
Add public function __construct()
with a MarkdownTransformer
argument. I'll hold
option
+enter
and select "Initialize fields" as a shortcut. Again, this just added
the property for me and assigned it in __construct()
:
// ... lines 1 - 6 | |
class MarkdownExtension extends \Twig_Extension | |
{ | |
private $markdownTransformer; | |
public function __construct(MarkdownTransformer $markdownTransformer) | |
{ | |
$this->markdownTransformer = $markdownTransformer; | |
} | |
// ... lines 15 - 31 | |
} |
Go Deeper!
Watch our PhpStorm Course to learn about these great shortcuts.
In parseMarkdown()
, return $this->markdownTransformer->parse()
and pass it $str
:
// ... lines 1 - 6 | |
class MarkdownExtension extends \Twig_Extension | |
{ | |
// ... lines 9 - 22 | |
public function parseMarkdown($str) | |
{ | |
return $this->markdownTransformer->parse($str); | |
} | |
// ... lines 27 - 31 | |
} |
The last step is to update our service in services.yml
. Add arguments: ['@app.markdown_transformer']
:
// ... lines 1 - 5 | |
services: | |
// ... lines 7 - 10 | |
app.markdown_extension: | |
// ... lines 12 - 14 | |
arguments: ['@app.markdown_transformer'] |
Refresh! And it's working. Now, let me show you a shortcut.
I'm getting a really strange error:
Cannot autowire service "AppBundle\Service\MarkdownTransformer": argument "$cache" of method "__construct()" references interface "Doctrine\Common\Cache\Cache" but no such service exists. You should maybe alias this interface to one of these existing services: "annotations.filesystem_cache", "annotations.cache", "doctrine_cache.providers.doctrine.orm.default_metadata_cache", "doctrine_cache.providers.doctrine.orm.default_result_cache", "doctrine_cache.providers.doctrine.orm.default_query_cache", "doctrine_cache.providers.my_markdown_cache".
I've tried adding this 'Knp\Bundle\MarkdownBundle\MarkdownParserInterface: '@markdown.parser'' into services.yaml but it doesn't work.
Please help.