如何在Symfony 3的Twig视图的Dates上使用time_diff和ago(time ago)函数

本文概述

  • A.捆绑(简单)方式
  • B.自我实现的方式
在许多Web应用程序和网站上, 你都可以查看日期并轻松阅读日期, 而无需知道今天是星期几, 也可以不知道哪一天是5月21日, 一月等。通常在浏览器中使用JavaScript即可实现此功能。所以有什么问题?用于格式化的库不是(通常)轻量级的, 你最终将获得至少3个库来实现类似的目的。如果你想在应用程序中实现这种功能, 而无需在视图上动态更新日期, 则可以在自己的服务器上执行此任务。
在本文中, 我们将向你展示两种显示时间格式的日期的方法:使用KnpTimeBundle(a)或实现Twig的Twig_Extensions_Extension_Date扩展。两者都提供相同的功能, 但是对于某些开发人员来说, 1的实现可能会更长一些, 因此由你决定哪种方法更容易实现。
A.捆绑(简单)方式如果你不必担心应用程序的大小, 并且可以安装第三方捆绑软件, 则可以更轻松地实现目标(容易得多):
1.安装并注册KnpTimeBundle
我们正在谈论KnpTimeBundle。该捆绑包完成一项简单的工作:记录日期并返回友好的” 2小时前” 类型的消息。要在你的Symfony项目中安装此捆绑包, 请在终端上执行以下命令:
composer require knplabs/knp-time-bundle

有关此捆绑包的更多信息, 请访问Github上的官方存储库。捆绑软件安装完成后, 请确保在Symfony内核(app / AppKernel.php)中启用捆绑软件:
< ?php// app/AppKernel.phppublic function registerBundles(){$bundles = [// ...new Knp\Bundle\TimeBundle\KnpTimeBundle(), // ...]; // ...}

你已经准备好继续下一步。
2.添加应用程序区域设置并启用翻译器
通常, 在每个默认的Symfony应用程序上, 语言环境已经存在, 默认情况下为en(英语)。此值不仅在分发包中用在整个应用程序中。如果不存在, 请为locale参数提供你自己语言的标识符:
注意有很多受支持的语言, 因此请确保检查翻译文件以了解受支持的语言。
parameters:locale: en# Or the locale of your language e.g : es, de, nl, pt, pl etc

接下来, 你需要启用翻译器, 因为它通常会被注释, 因此请确保你对app / config / config.yml文件中的翻译器设置未添加注释, 并且回退使用先前声明的locale参数:
framework:translator: { fallbacks: ['%locale%'] }

完成此操作后, 你将能够使用捆绑软件的前一个过滤器来显示时差的可读描述。
3.使用Twig ago过滤器
KnpTimeBundle即在以前公开了一个新的树枝过滤器。此过滤器期望将引用$ since的DateTime对象(起始日期)作为目标, 并使用可选参数$ to指定应该从何处进行差异(另一个DateTime对象), 例如:
{#In this example we convert the now string to a dateThe date can be retrieven from the controller etc.#}{% set myDate = "now"|date %}{#Modify our date by removing 4 days#}{% set myDate = myDate|date_modify('-4 day') %}{# Displays according to your locale: 4 days ago vor 4 Tagenhace 4 díasetc#}{{ myDate|ago}}{#And if you need to differentiate the date from another day but not nowprovide the first argument:#}{% set fromTomorrow = "now"|date_modify('+1 day') %}{# Displays according to your locale: 5 days agovor 5 Tagenhace 5 díasetc#}{{ myDate|ago(fromTomorrow)}}

容易不是吗?
B.自我实现的方式如果你今天很快乐并且有时间浪费, 那么你可能会学到一些新东西。自我实施的方式需要更多的实施时间, 但是如果你无法安装第三方捆绑软件, 那么这是你的最佳选择。
1.创建Twig_Extensions_Extension_Date扩展
首先, 你需要在项目中创建Twig_Extensions_Extension_Date扩展。此类是指Fabien Potencier对Twig进行的正式日期扩展。此类的优点是, 它也可以使用Symfony的翻译器模块, 因此它类似于第一步的捆绑软件。
【如何在Symfony 3的Twig视图的Dates上使用time_diff和ago(time ago)函数】在应用程序的某些目录上创建扩展文件, 即Twig_Extensions_Extension_Date.php, 并根据你的名称空间更改名称空间。在这种情况下, 我们将在AppBundle的Extensions文件夹内创建类:
< ?phpnamespace AppBundle\Extensions; /** * This file is part of Twig. * * (c) 2014 Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */use Symfony\Component\Translation\TranslatorInterface; use Twig_Environment; use Twig_SimpleFilter; use Twig_Extension; /** * @author Robin van der Vleuten < robinvdvleuten@gmail.com> */class Twig_Extensions_Extension_Date extends Twig_Extension{public static $units = array('y' => 'year', 'm' => 'month', 'd' => 'day', 'h' => 'hour', 'i' => 'minute', 's' => 'second', ); /*** @var TranslatorInterface*/private $translator; public function __construct(TranslatorInterface $translator = null){$this-> translator = $translator; }/*** {@inheritdoc}*/public function getFilters(){return array(new Twig_SimpleFilter('time_diff', array($this, 'diff'), array('needs_environment' => true)), ); }/*** Filter for converting dates to a time ago string like Facebook and Twitter has.** @param Twig_Environment $enva Twig_Environment instance* @param string|DateTime$date a string or DateTime object to convert* @param string|DateTime$nowA string or DateTime object to compare with. If none given, the current time will be used.** @return string the converted time*/public function diff(Twig_Environment $env, $date, $now = null){// Convert both dates to DateTime instances.$date = twig_date_converter($env, $date); $now = twig_date_converter($env, $now); // Get the difference between the two DateTime objects.$diff = $date-> diff($now); // Check for each interval if it appears in the $diff object.foreach (self::$units as $attribute => $unit) {$count = $diff-> $attribute; if (0 !== $count) {return $this-> getPluralizedInterval($count, $diff-> invert, $unit); }}return ''; }protected function getPluralizedInterval($count, $invert, $unit){if ($this-> translator) {$id = sprintf('diff.%s.%s', $invert ? 'in' : 'ago', $unit); return $this-> translator-> transChoice($id, $count, array('%count%' => $count), 'date'); }if (1 !== $count) {$unit .= 's'; }return $invert ? "in $count $unit" : "$count $unit ago"; }/*** {@inheritdoc}*/public function getName(){return 'date'; }}

2.添加应用程序区域设置并启用翻译器
通常, 在每个默认的Symfony应用程序上, 语言环境已经存在, 默认情况下为en(英语)。此值不仅在分发包中用在整个应用程序中。如果不存在, 请为locale参数提供你自己语言的标识符:
parameters:locale: en# Or the locale of your language e.g : es, de, nl, pt, pl etc

接下来, 你需要启用翻译器, 因为它通常会被注释, 因此请确保你对app / config / config.yml文件中的翻译器设置未添加注释, 并且回退使用先前声明的locale参数:
framework:translator: { fallbacks: ['%locale%'] }

完成后, 你将可以在扩展程序上使用翻译器模块。
3.注册扩展
接下来, 继续使用翻译服务作为参数注册扩展, 并提供上一步的类的路径:
services:twig.extension.date:# the namespace with the name of the Twig Extensions created classclass: AppBundle\Extensions\Twig_Extensions_Extension_Datearguments: ["@translator"]tags:-{ name: twig.extension }

4.创建翻译文件
接下来, 你需要创建翻译文件, 但是对于像我这样的懒惰开发人员而言, 总有一种使一切变得容易的方法。在这种情况下, 翻译文件将采用xliff格式, 因为我们可以复制KnpTimeBundle的翻译, 因此我们不需要编写自己的翻译文件。但是, 请注意, KnpTimeBundle中的名称空间是时间, 但由于服务twig.extension.date的提供者名称, 此扩展名中的日期是date。
转到此处的KnpTimeBundle的翻译文件, 然后选择所需的文件并将其复制到项目的app / Resources / translations /文件夹中(如果不存在translations文件夹, 则创建它)。例如, 以下文件(app / Resources / translations / date.de.xliff)用德语提供了我们日期的翻译:
重要请注意, 每个反式交易单元的ID是一个字符串。在KnpTimeBundle的存储库中, id是数字, 因此请确保通过source属性的内容更改ID, 否则Symfony将找不到任何要翻译的项目。 xliff文件的名称必须遵循文件名模式(在这种情况下)日期。< lang-identifier> .xliff。
< ?xml version="1.0"?> < xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> < file source-language="en" datatype="plaintext" original="file.ext"> < body> < trans-unit id="diff.ago.year"> < source> diff.ago.year< /source> < target> vor einem Jahr|vor %count% Jahren< /target> < /trans-unit> < trans-unit id="diff.ago.month"> < source> diff.ago.month< /source> < target> vor einem Monat|vor %count% Monaten< /target> < /trans-unit> < trans-unit id="diff.ago.day"> < source> diff.ago.day< /source> < target> vor %count% Tag|vor %count% Tagen< /target> < /trans-unit> < trans-unit id="diff.ago.hour"> < source> diff.ago.hour< /source> < target> vor einer Stunde|vor %count% Stunden< /target> < /trans-unit> < trans-unit id="diff.ago.minute"> < source> diff.ago.minute< /source> < target> vor einer Minute|vor %count% Minuten< /target> < /trans-unit> < trans-unit id="diff.ago.second"> < source> diff.ago.second< /source> < target> vor einer Sekunde|vor %count% Sekunden< /target> < /trans-unit> < trans-unit id="diff.empty"> < source> diff.empty< /source> < target> jetzt< /target> < /trans-unit> < trans-unit id="diff.in.second"> < source> diff.in.second< /source> < target> in einer Sekunde|in %count% Sekunden< /target> < /trans-unit> < trans-unit id="diff.in.hour"> < source> diff.in.hour< /source> < target> in einer Stunde|in %count% Stunden< /target> < /trans-unit> < trans-unit id="diff.in.minute"> < source> diff.in.minute< /source> < target> in einer Minute|in %count% Minuten< /target> < /trans-unit> < trans-unit id="diff.in.day"> < source> diff.in.day< /source> < target> in einem Tag|in %count% Tagen< /target> < /trans-unit> < trans-unit id="diff.in.month"> < source> diff.in.month< /source> < target> in einem Monat|in %count% Monaten< /target> < /trans-unit> < trans-unit id="diff.in.year"> < source> diff.in.year< /source> < target> in einem Jahr|in %count% Jahren< /target> < /trans-unit> < /body> < /file> < /xliff>

5.在视图中使用time_diff过滤器
以与KnpTimeBundle的前一个过滤器相同的方式, time_diff过滤器期望将引用$ since(原始日期)的DateTime对象作为目标, 并使用可选参数$ to指定应该从何处进行差值(另一个DateTime)。对象), 例如:
{#In this example we convert the now string to a dateThe date can be retrieven from the controller etc.#}{% set myDate = "now"|date %}{#Modify our date by removing 4 days#}{% set myDate = myDate|date_modify('-4 day') %}{# Displays according to your locale: 4 days ago vor 4 Tagenhace 4 díasetc#}{{ myDate|time_diff}}{#And if you need to differentiate the date from another day but not nowprovide the first argument:#}{% set fromTomorrow = "now"|date_modify('+1 day') %}{# Displays according to your locale: 5 days agovor 5 Tagenhace 5 díasetc#}{{ myDate|time_diff(fromTomorrow)}}

编码愉快!

    推荐阅读