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!
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.
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.
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
That's odd, I don't see anything in the KnpLabs/KnpTimeBundle
repository that asks for symfony/lts 4.x-dev
. Actually, that package is deprecated, that's why it's not compatible with Symfony5. I'm not sure why that's happening, perhaps you should try upgrading Compose and clearing its cache, and then, try again to install it
Cheers!
HI team !
i had a problem when installing KnpTimeBundle showed as:
`
Your requirements could not be resolved to an installable set of packages.
Problem 1
- symfony/config v5.1.0 requires php >=7.2.5 -> your PHP version (7.4.5) overridden by "config.platform.php" version (7.1.3) does not satisfy that requirement.
- symfony/config v5.0.9 requires php >=7.2.5 -> your PHP version (7.4.5) overridden by "config.platform.php" version (7.1.3) does not satisfy that requirement.
- Can only install one of: symfony/config[v4.4.7, v4.0.14].
- Can only install one of: symfony/config[v4.4.9, v4.0.14].
- Installation request for symfony/config (locked at v4.0.14) -> satisfiable by symfony/config[v4.0.14].
Installation failed, reverting ./composer.json to its original content.`
= symfony version was 4.0 then i changed requires in composer.json to
"symfony/asset": "^4.4",
"symfony/console": "^4.4",
= i run composer update, then i had another error that there helped me out with it in another tutorial,
Cannot autowire service "App\Repository\ArticleRepository": argument "$registry" of method "__construct()" references interface "Symfony\Bridge\
!! Doctrine\RegistryInterface" but no such service exists. Try changing the type-hint to "Doctrine\Persistence\ManagerRegistry" instead.
I did followed the messag type-hint, afterwards i could finally run composer require knplabs/knp-time-bundle and it worked.
The problem is that, there is an error in the constructor of ArticleRepository, precisely under the parent:: property , i when i hover, the IDE shows :
Cannot use 'parent' in a class with no parent.intelephense(1035)
Peek Problem (Alt+F8)
No quick fixes available
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Article::class);
}
My question is, Does this error come from my IDE or did i change something that i should not while configuring the project ? Thanks
Hey Raed,
If you look into your composer.json - you will find that it has "config.platform.php" section in it and PHP is locked at 7.1.3 by us. That was made because we don't want to lock project dependencies on the latest PHP version as users with lower PHP version won't be able to install it. So, technically, you can bump that PHP version to 7.2.5 as required by Symfony and then Composer should be able to install it. Actually, you can even remove that config.platform.php section at all and then Composer will base on your current PHP version only, but keep that config.platform.php is a good idea, especially when you have different PHP versions on production on locally. Ideally you should set that config.platform.php version to the one you use on production to make sure all the dependencies you're installing locally will work on production's PHP version :)
But I suppose you got that error not on installing KnpTimeBundle but on executing "composer update", as it clearly wants to upgrade symfony versions. But if it's something you intended to do - then follow the solution I mentioned above. If not - try to just install locked dependencies with "composer install" execute only "composer require %bundle-name%" to install the KnpTimeBundle without upgrading existent packages.
I hope it's clear for you!
Cheers!
Hey victor ,
Thank you so much for your reply ! This helped solve the problem and understand the concept !
Hello, i have this error when user composer to install knpTimeBundle
~Dev/the_spacebartest$ composer require knplabs/knp-time-bundle
Using version ^1.11 for knplabs/knp-time-bundle
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Conclusion: remove symfony/lts 4.x-dev
- Conclusion: don't install symfony/lts 4.x-dev
- symfony/config v5.0.0 conflicts with symfony/lts[4.x-dev].
- symfony/config v5.0.1 conflicts with symfony/lts[4.x-dev].
- symfony/config v5.0.2 conflicts with symfony/lts[4.x-dev].
- Installation request for symfony/lts ^4@dev -> satisfiable by symfony/lts[4.x-dev].
- Installation request for knplabs/knp-time-bundle ^1.11 -> satisfiable by knplabs/knp-time-bundle[v1.11.0].
- Conclusion: don't install symfony/config v4.0.14|install
symfony/config v5.0.0|install symfony/config v5.0.1|install
symfony/config v5.0.2
- Conclusion: remove symfony/config
v4.0.14|install symfony/config v5.0.0|install symfony/config
v5.0.1|install symfony/config v5.0.2
- knplabs/knp-time-bundle
v1.11.0 requires symfony/config ~3.4|^4.3|^5.0 -> satisfiable by
symfony/config[v3.4.0, v3.4.1, v3.4.10, v3.4.11, v3.4.12, v3.4.13,
v3.4.14, v3.4.15, v3.4.16, v3.4.17, v3.4.18, v3.4.19, v3.4.2, v3.4.20,
v3.4.21, v3.4.22, v3.4.23, v3.4.24, v3.4.25, v3.4.26, v3.4.27, v3.4.28,
v3.4.29, v3.4.3, v3.4.30, v3.4.31, v3.4.32, v3.4.33, v3.4.34, v3.4.35,
v3.4.36, v3.4.4, v3.4.5, v3.4.6, v3.4.7, v3.4.8, v3.4.9, v4.3.0, v4.3.1,
v4.3.2, v4.3.3, v4.3.4, v4.3.5, v4.3.6, v4.3.7, v4.3.8, v4.3.9, v4.4.0,
v4.4.1, v4.4.2, v5.0.0, v5.0.1, v5.0.2].
- Can only install one of: symfony/config[v3.4.0, v4.0.14].
- Can only install one of: symfony/config[v3.4.1, v4.0.14].
- Can only install one of: symfony/config[v3.4.10, v4.0.14].
- Can only install one of: symfony/config[v3.4.11, v4.0.14].
- Can only install one of: symfony/config[v3.4.12, v4.0.14].
- Can only install one of: symfony/config[v3.4.13, v4.0.14].
- Can only install one of: symfony/config[v3.4.14, v4.0.14].
- Can only install one of: symfony/config[v3.4.15, v4.0.14].
- Can only install one of: symfony/config[v3.4.16, v4.0.14].
- Can only install one of: symfony/config[v3.4.17, v4.0.14].
- Can only install one of: symfony/config[v3.4.18, v4.0.14].
...
Thanks
Hey LE Xuan Hung,
First of all, "symfony/lts" is deprecated package in favor of Symfony Flex... if you have it in your composer.json, you can remove it. But that's minor. About the problem installing KnpTimeBundle - what version of Symfony do you have? Are you trying to install it on your own project? Or did you download the course code and work in start/ directory of it? Are you able to install dependencies successfully without KnpTimeBundle executing "composer install"? Do you see any errors?
Cheers!
Hello Victor,
After running composer update, i can install knptime bundle now.
Otherwise,
I have downloaded the source code and used start directory. I have Symfony version 4.4.2
`
bin/console --version
Symfony 4.4.2 (env:dev, debug: true)
`
Thanks you for help.
Hey LE Xuan Hung,
Glad to hear you got it working! Looks like the bundle required some dependencies you had to be updated as well and composer wasn't able to solve this issue itself.
Cheers!
This bundle relies on the Twig/Extensions Bundle (Which is abandoned) and isn't compatible with SF 5 and Twig 3 (Twig 3 ships normally with SF 4.4, so its even incompatible out of the box with SF 4.4).
https://github.com/KnpLabs/...
Is there any alternative? Will this bundle get fixed?
Hey Mike P.
I think that bundle just got support for Syfmony5 and 4.4, you should give it a try
Cheers!
There seems to be a solution:
https://github.com/KnpLabs/...
But MolloKhan needs to merge this commit to make the bundle compatible with twig 3 & sf 5.
Hey Mike P.!
Thanks for the poke - I've got that PR merged and a new release tagged :).
Cheers!
Like Manoj said in the comment below, its not working.
You are right, Ryan said that this bundle is now compatible with SF5 (In the release notes), but its not.
When I install knpTimeBundle via composer I get this error:
!! 17:12:38 CRITICAL [php] Uncaught Error: Class 'Twig_Extension' not found ["exception" => Error { …}]
...
!! In TimeExtension.php line 20:
!!
!! Attempted to load class "Twig_Extension" from the global namespace.
!! Did you forget a "use" statement?
Thats because it relies on the twig/extensions bundle.
And when I try to install it via:
composer require twig/extensions
I get this error:
Restricting packages listed in "symfony/symfony" to "5.0.*"
Your requirements could not be resolved to an installable set of packages.
Because the twig/extensions bundle got abandoned by Fabian.
WARNING: This repository is abandoned in favor of Twig Core Extra extensions.
...
DateExtension: time_diff filter -> no equivalent
So the knpTimeBundle by itself maybe is compatible with SF5, but the required twig/extensions bundle to use it is incompatible with Twig3 & SF 5, that's why we can't use it.
Any advice MolloKhan how to make it work again?
Hey infete!
It should be working now - I had a bug in a release of KnpTimeBundle, which has now been fixed.
Cheers!
After installing the time bundle with composer require knplabs/knp-time-bundle
I get this error:
Script cache:clear returned with error code 255
`<br />Error: During class fetch: Uncaught ReflectionException: Class Symfony\Comp <br />!! onent\Form\FormTypeGuesserInterface not found in /Users/john_christensen/Do <br />!! wnloads/code-symfony-doctrine/start/vendor/symfony/doctrine-bridge/Form/Doc <br />!! trineOrmTypeGuesser.php:25 <br />!! Stack trace: <br />!! #0 /Users/john_christensen/Downloads/code-symfony-doctrine/start/vendor/sym <br />!! fony/debug/DebugClassLoader.php(145): require('/Users/john_chr...') <br />!! #1 [internal function]: Symfony\Component\Debug\DebugClassLoader->loadClass <br />!! ('Symfony\\Bridge\\...') <br />!! #2 [internal function]: spl_autoload_call('Symfony\\Bridge\\...') <br />!! #3 /Users/john_christensen/Downloads/code-symfony-doctrine/start/vendor/sym <br />!! fony/config/Resource/ClassExistenceResource.php(76): class_exists('Symfony\ <br />!! \Bridge\\...') <br />!! #4 /Users/john_christensen/Downloads/code-symfony-doctrine/start/vendor/sym <br />!! fony/dependency-injection/ContainerBuilder.php(350): Symfony\Component\Conf <br />!! ig\Resource\ClassExistenceResource->isFresh(0) <br />!! #5 /Users/john_christensen/Downloads/code-symfony-doctrine/start/vendor/sym <br />!! fony/dependency-inje
which appears to be this flex issue:
https://github.com/symfony/flex/issues/329
Also.. if I start with the tutorial 'finish' folder and do a composer install
I still get this error.
So has something changed with symfony/flex? Any idea how to resolve this?
Thx!
I figured it out..
Apparently this is a PHP compatibility issue. The error occurs with PHP 7.2.20 and 7.3.7.
Downgrading to PHP 7.1.30 solves the problem.
Hey Ozornick,
Yeah, upgrading to the newest PHP version 7.3.8 should be the best option I think. Thanks for the tip!
Cheers!
Hey John,
Yeah, it's a known issue on PHP 7.2.20 / 7.3.7. Upgrading to the latest PHP version should solve the issue - there's a new release 7.2.21 / 7.3.8. But in case you can't upgrade to the latest for some reasons - you can temporarily workaround it by installing missing packages - symfony/form in your case.
Cheers!
Ok thx. Fyi.. I did try installing the form package, but get the same error. I had to downgrade php to 7.1.30 just to get the package to install. But if I then run php 7.2.20 or 7.3.7, I get the 'uncaught ReflectionException' error. I am using MAMP PRO which does not have php 7.3.8 yet, so I guess I will just run with 7.1 for now.
Hey John,
Are you sue you had exactly the same missing file, i.e. "Symfony\Component\Form\FormTypeGuesserInterface" after did "composer require form"? Because that file IS from the symfony/form repo, you check see the file there: https://github.com/symfony/... . Most probably after installing it there was a similar error but with another file name, that you would need to require as well. Or probably it was cache, try to clear it first.
Anyway, I'm glad you found a solution that works for you!
Cheers!
I would only publish those blogs that have publishedAt field equal not null. The "if" statement should be at PHP side.
Hey Abelardo L.
That is true, frontend should load quick but in this case, we are rendering HTML on the server, so it won't make any difference. If you ask me, I would do that filtering at DB level.
Cheers!
Is it possible to cache the 'ago' time or does this Bundle do it automatically for us? My question is, wouldn't it be better, performance wise, to calculate the time client side via Javascript? Of course I see the point of this example, being super simple.
Hey Mike,
Hm, it's probably too minor to worry about caching it. Actually, it's almost the same as use "|date" Twig filter, i.e. it's just a date formatter. Yes, you can use JavaScript to do things like this, but you would need to render the date object anyway to put the date into HTML, so you would need to use |date filter anyway. And so, why not use |ago filter instead? There's no any time-consuming calculations behind the scene, you would probably need to worry about how to cache the entity itself to avoid hitting MySQL - would have more sense :)
Btw you can use Blackfire.io to profile the performance and see some bottle necks in your project. But if you do think that "|ago" hit your performance, probably better to cache the whole page. And yes, in *that* case you would need to render dates with JavaScript.
Cheers!
Filter {{page.dateCreate | ago}} returns the date in the format "diff.ago.month". How to change the date format, as shown in the video?
Hey Dmitriy,
As far as I remember this bundle uses smart format. If you did something a few minutes ago, it would use "diff.ago.minute", but if you did something a few years ago, it would use "diff.ago.year". So, it automatically detects how far is the given date from now, and depends on it uses different formats. Is it clear for you now? Is it OK for you? If not, you'd probably need to override the main logic of this bundle somehow, because I see this bundle does not have any configuration options.
I hope this helps.
Cheers!
Thank you, Victor. I just copied the "EN" language file from / vendor / knplabs / knp-time-bundle / Knp / Bundle / TimeBundle / Resources / translations into the root translations folder and it all worked.
Hey Dmitriy,
Wait, do you mean that "diff.ago.month" string wasn't translated before? If so, then I misunderstood you :) Well, coping the translation file into your project might help, but it really should work out of the box. I think you needed just clear the cache before instead of copying it. So, you can try to clear cache first.
Cheers!
Perfect! :) Yes, translations is probably the only place where you have to clear the cache for new translation files. So, it's always a good idea to start with clearing cache before going further.
Cheers!
Hello,
knp-markdown-bundle causes a "A tree builder without a root node is deprecated since Symfony 4.2" error in Symfony 4.2.
Someone already made a fix which is awaiting being merged:
https://github.com/KnpLabs/...
The issue and associated MR has been opened a few weeks ago, hopefully the maintainer or someone with the rights to merge is still aware of this project and merges the fix.
Hi Guys,
following error shows up while installing the bundle :
The autoloader expected class "Knp\Bundle\MarkdownBundle\Helper\MarkdownHelper" to be defined in file "D:\dev\the-spacebar\vendor\composer/../knplabs/knp-markdown-bundle\Helper\MarkdownHelper.php". The file was found but the class was not in it, the class name or namespace probably has a typo.
This is the MarkdownHelper.php file:
namespace App\Service;
use Michelf\MarkdownInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Cache\Adapter\AdapterInterface;
class MarkdownHelper
{
private $cache;
private $markdown;
private $logger;
private $isDebug;
public function __construct(AdapterInterface $cache, MarkdownInterface $markdown, LoggerInterface $markdownLogger, bool $isDebug)
{
$this->cache = $cache;
$this->markdown = $markdown;
$this->logger = $markdownLogger;
$this->isDebug = $isDebug;
}
public function parse(string $source): string
{
if (stripos($source, 'bacon') !== false) {
$this->logger->info('They are talking about bacon again!');
}
// skip caching entirely in debug
if ($this->isDebug) {
return $this->markdown->transform($source);
}
$item = $this->cache->getItem('markdown_'.md5($source));
if (!$item->isHit()) {
$item->set($this->markdown->transform($source));
$this->cache->save($item);
}
return $item->get();
}
}
Hey again Kristof Kreimeyer !
Oh geez - this is a nasty error! The problem is not in your code at all - which is very confusing. The error is being very accurate: it basically says that it's looking for this MarkdownHelper file - which is part of a vendor library - and it found the file where that class should live, but it's not inside. That... makes no sense :). If you, for example, handled installed KnpMarkdownBundle, then the file wouldn't exist at all. The fact that the file - D:\dev\the-spacebar\vendor\composer/../knplabs/knp-markdown-bundle\Helper\MarkdownHelper.php
- exists but has the wrong contents is a total mystery.
So, my only explanation is that something either went strange with Composer or, perhaps, your IDE (PhpStorm can do this) got over-excited when you were (for example) renaming something and renamed things deep inside of this core library. Try this to fix it:
rm -rf vendor
composer install
Between this question and your previous one, something definitely went very wrong (e.g. PhpStorm renaming too much code) - I think these errors are caused by something outside of what you're doing.
Let me know what you find out!
Cheers!
Can we cache the result of "ago" function, like we did with "parse" in the previous tutorial? If so, what is the logic of invalidation of this value (because date and time flow constantly and it seems that we could cache it for long periods like "a year ago", but can not for "2 hours ago")? If we can not cache this value, will it be more convenient (for a real world project) to make this job on a client side with javascript and to print a full datetime string in a template?
Hey @Mehdi Marchouk
How's the structure of your Phone entity?
Does it contains a relationship to Person and another one to Business?
If that's the case you can set up an "UniqueConstraint" at the table level. Check this example: https://www.doctrine-projec...
Cheers!
// composer.json
{
"require": {
"php": "^7.1.3",
"ext-iconv": "*",
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"knplabs/knp-markdown-bundle": "^1.7", // 1.7.0
"knplabs/knp-time-bundle": "^1.8", // 1.8.0
"nexylan/slack-bundle": "^2.0,<2.2.0", // v2.0.0
"php-http/guzzle6-adapter": "^1.1", // v1.1.1
"sensio/framework-extra-bundle": "^5.1", // v5.1.4
"stof/doctrine-extensions-bundle": "^1.3", // v1.3.0
"symfony/asset": "^4.0", // v4.0.4
"symfony/console": "^4.0", // v4.0.14
"symfony/flex": "^1.0", // v1.17.6
"symfony/framework-bundle": "^4.0", // v4.0.14
"symfony/lts": "^4@dev", // dev-master
"symfony/orm-pack": "^1.0", // v1.0.6
"symfony/twig-bundle": "^4.0", // v4.0.4
"symfony/web-server-bundle": "^4.0", // v4.0.4
"symfony/yaml": "^4.0" // v4.0.14
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.0", // 3.0.2
"easycorp/easy-log-handler": "^1.0.2", // v1.0.4
"fzaninotto/faker": "^1.7", // v1.7.1
"symfony/debug-bundle": "^3.3|^4.0", // v4.0.4
"symfony/dotenv": "^4.0", // v4.0.14
"symfony/maker-bundle": "^1.0", // v1.4.0
"symfony/monolog-bundle": "^3.0", // v3.1.2
"symfony/phpunit-bridge": "^3.3|^4.0", // v4.0.4
"symfony/profiler-pack": "^1.0", // v1.0.3
"symfony/var-dumper": "^3.3|^4.0" // v4.0.4
}
}
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!