我需要做一个自定义过滤器,将价格转换为用户货币偏好。所以我每天都有一张更新最新汇率的表格。
我打算这样调用过滤器 {{ '200'|price }} 或 {{ '200'|price('USD') }}
过滤器将首先从 cookie 中获取用户偏好。
然后它会根据货币代码查询最新汇率并转换实际价格。
我的问题是,是否可以在树枝扩展中进行数据库查询(在此处过滤)。
我可能必须在一个页面中调用此过滤器 10 次。这是否意味着还有 10 个查询?
你会建议什么更好的方法?
我需要做一个自定义过滤器,将价格转换为用户货币偏好。所以我每天都有一张更新最新汇率的表格。
我打算这样调用过滤器 {{ '200'|price }} 或 {{ '200'|price('USD') }}
过滤器将首先从 cookie 中获取用户偏好。
然后它会根据货币代码查询最新汇率并转换实际价格。
我的问题是,是否可以在树枝扩展中进行数据库查询(在此处过滤)。
我可能必须在一个页面中调用此过滤器 10 次。这是否意味着还有 10 个查询?
你会建议什么更好的方法?
是的,如果您没有为 Doctrine 定义缓存配置,则意味着您每次都会向数据库发送请求以获取数据。
您可以选择查询汇率、自己将它们存储在缓存中或使用 Doctrine 的缓存功能来完成。
这两种方式都比每次都直接从数据库中查询数据要好。
使用学说事件系统,在这种情况下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')] }}
您可以创建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 缓存可能会加快速度,但任何缓存都会导致额外的问题和问题:
等等。