ago Filter with KnpTimeBundle
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.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeOk, I just need to show you something fun - it deals with Twig filters. See this 4 hours ago? That's still hard coded! Find the show template and scroll up a bit to find it:
// ... lines 1 - 4 | |
{% block body %} | |
<div class="container"> | |
<div class="row"> | |
<div class="col-sm-12"> | |
<div class="show-article-container p-3 mt-4"> | |
<div class="row"> | |
<div class="col-sm-12"> | |
// ... line 13 | |
<div class="show-article-title-container d-inline-block pl-3 align-middle"> | |
// ... lines 15 - 17 | |
<span class="pl-2 article-details"> 4 hours ago</span> | |
// ... lines 19 - 22 | |
</div> | |
</div> | |
</div> | |
// ... lines 26 - 71 | |
</div> | |
</div> | |
</div> | |
</div> | |
{% endblock %} | |
// ... lines 78 - 83 |
There!
Printing a DateTime Object in Twig
The Article
entity has a $publishedAt
property, so let's get our act together and starting using that to print out the real date. Oh, but remember: the $publishedAt
field might be null
if the article has not been published yet. So let's use the fancy ternary syntax to say: {{ article.publishedAt }}
, then, if it is published, print article.publishedAt
. But, publishedAt
is a DateTime
object... and you can't just run around printing DateTime
objects, and expect PHP to not get angry.
To fix that, pipe this through a date
filter, and then say Y-m-d
:
// ... lines 1 - 4 | |
{% block body %} | |
<div class="container"> | |
<div class="row"> | |
<div class="col-sm-12"> | |
<div class="show-article-container p-3 mt-4"> | |
<div class="row"> | |
<div class="col-sm-12"> | |
// ... line 13 | |
<div class="show-article-title-container d-inline-block pl-3 align-middle"> | |
// ... lines 15 - 17 | |
<span class="pl-2 article-details"> | |
{{ article.publishedAt ? article.publishedAt|date('Y-m-d') : 'unpublished' }} | |
</span> | |
// ... lines 21 - 24 | |
</div> | |
</div> | |
</div> | |
// ... lines 28 - 73 | |
</div> | |
</div> | |
</div> | |
</div> | |
{% endblock %} | |
// ... lines 80 - 85 |
Most filters do not have any arguments - most are like cached_markdown
. But filters are allowed to have arguments. If the article is not published, just say that: unpublished:
// ... lines 1 - 4 | |
{% block body %} | |
<div class="container"> | |
<div class="row"> | |
<div class="col-sm-12"> | |
<div class="show-article-container p-3 mt-4"> | |
<div class="row"> | |
<div class="col-sm-12"> | |
// ... line 13 | |
<div class="show-article-title-container d-inline-block pl-3 align-middle"> | |
// ... lines 15 - 17 | |
<span class="pl-2 article-details"> | |
{{ article.publishedAt ? article.publishedAt|date('Y-m-d') : 'unpublished' }} | |
</span> | |
// ... lines 21 - 24 | |
</div> | |
</div> | |
</div> | |
// ... lines 28 - 73 | |
</div> | |
</div> | |
</div> | |
</div> | |
{% endblock %} | |
// ... lines 80 - 85 |
Love it! When we go back and refresh, published on March 20th.
Installing KnpTimeBundle
Cool... but it looked better when it said something like "five minutes ago" or "two weeks ago" - that was way more hipster. The date... it's ugly!
Fortunately, there's a really simple bundle that can convert your dates into this cute "ago" format. Search for KnpTimeBundle. Despite seeing my little face there, I did not create this bundle, so I take no credit for it. I just think it's great.
Scroll down to the "composer require" line, copy that, find your terminal and, paste!
composer require knplabs/knp-time-bundle
This installs the bundle and... interesting! It also installs symfony/translation
. Behind the scenes, KnpTimeBundle uses the translator to translate the "ago" wording into other languages.
But what's really cool is that symfony/translation
has a Flex recipe. Before I recorded this chapter, I committed our changes so far. So now I can run:
git status
to see what that sneaky translation recipe did. Interesting: we have a new config/packages/translation.yaml
file and a new translations/
directory where any translation files should live... if we need any.
At a high level, the recipe system, like always, is making sure that everything is setup for us, automatically.
Using the ago Filter
Ok, let's use that filter! Back in the template, replace the date
filter with |ago
:
// ... lines 1 - 4 | |
{% block body %} | |
<div class="container"> | |
<div class="row"> | |
<div class="col-sm-12"> | |
<div class="show-article-container p-3 mt-4"> | |
<div class="row"> | |
<div class="col-sm-12"> | |
// ... line 13 | |
<div class="show-article-title-container d-inline-block pl-3 align-middle"> | |
// ... lines 15 - 17 | |
<span class="pl-2 article-details"> | |
{{ article.publishedAt ? article.publishedAt|ago : 'unpublished' }} | |
</span> | |
// ... lines 21 - 24 | |
</div> | |
</div> | |
</div> | |
// ... lines 28 - 73 | |
</div> | |
</div> | |
</div> | |
</div> | |
{% endblock %} | |
// ... lines 80 - 85 |
That's it. Find the page, refresh and... perfect! 27 days ago. So much nicer!
Next, I want to talk a little bit more about the AppExtension
Twig extension because, for a very subtle but important reason, it has a performance problem.
Hey there
I just noticed what's your problem. You're trying to install a version of the library that doesn't support Symfony4.0, you need to install the version 1.10.0 https://github.com/KnpLabs/...
Give it a try and let me know if it didn't work
Cheers!