1

我需要做一个自定义过滤器,将价格转换为用户货币偏好。所以我每天都有一张更新最新汇率的表格。

我打算这样调用过滤器 {{ '200'|price }} 或 {{ '200'|price('USD') }}

过滤器将首先从 cookie 中获取用户偏好。

然后它会根据货币代码查询最新汇率并转换实际价格。

我的问题是,是否可以在树枝扩展中进行数据库查询(在此处过滤)。

我可能必须在一个页面中调用此过滤器 10 次。这是否意味着还有 10 个查询?

你会建议什么更好的方法?

4

3 回答 3

3

是的,如果您没有为 Doctrine 定义缓存配置,则意味着您每次都会向数据库发送请求以获取数据。

您可以选择查询汇率、自己将它们存储在缓存中或使用 Doctrine 的缓存功能来完成。

Symfony 2 缓存 Doctrine 查询结果

这两种方式都比每次都直接从数据库中查询数据要好。

于 2016-05-14T08:09:46.317 回答
2

使用学说事件系统,在这种情况下postLoad事件将是合适的。您可以将价格添加到实体中未映射的属性,然后在树枝中调用,例如:{{ entity.prices.usd }}

services:
    app.postload.listener:
        class: AppBundle\EventListener\PostLoadListener
        tags:
            - { name: doctrine.event_listener, event: postLoad }

监听类:

namespace AppBundle\EventListener;

use Doctrine\ORM\Event\LifecycleEventArgs;
use AppBundle\Entity\Product;



class PostLoadListener
{

protected static $currencies = [];

public function postLoad(LifecycleEventArgs $args)
{
    $entity = $args->getEntity();


    $entityManager = $args->getEntityManager();


    if ($entity instanceof Product) {
        $price = $entity->getPrice();
        if (empty($this->currencies) {
            // get currencies from db and calculate prices
            $this->currencies = $entityManager->getConnection()->prepare('SELECT.....')->execute()->fetchAll();
        }

        // Calculate prices and make them as array: $prices = ['usd' => 34, 'eur` => 30 .....]

    $entity->setPrices($prices);
}

}

在 Twig 中调用它们:

{{ entity.prices[app.request.cookies.get('currency')] }}
于 2016-05-14T08:19:37.973 回答
1

您可以创建CurrencyConverter只查询数据库一次的类,并假设在用户请求期间速率未更改,并使用其结果。一些简单的服务(您可以将其与 DI 一起注入到您的 Twig 扩展中),例如

class CurrencyConverter
{
    /** @var EntityManager */
    private $em;

    private $rates = [];

    public function __construct(EntityManager $em)
    {
        $this->em = $em;
    }

    public function convert($amount, $currency)
    {
        return $amount * $this->getRate($currency);
    }

    private function getRate($currency)
    {
        if (!isset($this->rates[$currency])) {
            $repository = $this->em->getRepository('AppBundle:Rate');
            $this->rates[$currency] = $repository->getLatestRate($currency);
        }

        return $this->rates[$currency];
    }
}

这样,每种货币的每个请求都会有 1 个数据库查询。如果您没有很多用户,那可能就足够了。MySQL 很可能会将整个汇率表加载到内存中,并且速度会非常快。

Doctrine 缓存可能会加快速度,但任何缓存都会导致额外的问题和问题:

  • 查询结果应该在缓存中保存多长时间?
  • 我需要在速率更新时手动清除缓存吗?
  • 我刚刚从缓存或数据库中得到结果吗?

等等。

于 2016-05-14T13:33:10.507 回答