个性化阅读
专注于IT技术分析

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

本文概述

在许多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.php

public 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 date
    The 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 Tagen
    hace 4 días
    etc
#}
{{ myDate|ago}}


{#
    And if you need to differentiate the date from another day but not now
    provide the first argument:
#}

{% set fromTomorrow = "now"|date_modify('+1 day') %}

{# Displays according to your locale: 
    5 days ago
    vor 5 Tagen
    hace 5 días
    etc
#}
{{ myDate|ago(fromTomorrow)}}

容易不是吗?

B.自我实现的方式

如果你今天很快乐并且有时间浪费, 那么你可能会学到一些新东西。自我实施的方式需要更多的实施时间, 但是如果你无法安装第三方捆绑软件, 那么这是你的最佳选择。

1.创建Twig_Extensions_Extension_Date扩展

首先, 你需要在项目中创建Twig_Extensions_Extension_Date扩展。此类是指Fabien Potencier对Twig进行的正式日期扩展。此类的优点是, 它也可以使用Symfony的翻译器模块, 因此它类似于第一步的捆绑软件。

在应用程序的某些目录上创建扩展文件, 即Twig_Extensions_Extension_Date.php, 并根据你的名称空间更改名称空间。在这种情况下, 我们将在AppBundle的Extensions文件夹内创建类:

<?php

namespace 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 $env  a Twig_Environment instance
     * @param string|DateTime  $date a string or DateTime object to convert
     * @param string|DateTime  $now  A 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 class
        class: AppBundle\Extensions\Twig_Extensions_Extension_Date
        arguments: ["@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 date
    The 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 Tagen
    hace 4 días
    etc
#}
{{ myDate|time_diff}}

{#
    And if you need to differentiate the date from another day but not now
    provide the first argument:
#}

{% set fromTomorrow = "now"|date_modify('+1 day') %}

{# Displays according to your locale: 
    5 days ago
    vor 5 Tagen
    hace 5 días
    etc
#}
{{ myDate|time_diff(fromTomorrow)}}

编码愉快!

赞(0)
未经允许不得转载:srcmini » 如何在Symfony 3的Twig视图的Dates上使用time_diff和ago(time ago)函数

评论 抢沙发

评论前必须登录!