我有两个实体。一个是WebshopItem实体,另一个是WebshopPrice实体。 每次,您正在创建一个WebshopItem,您还要填写3个WebshopPrices。网上商店价格是3种货币(欧元,美元和英镑)。
根据您选择的货币(并保存在您的会话中),我想显示您选择的货币。所以,如果您选择欧元,我当然希望显示欧元价格。
在symfony中执行此操作的一般方法是什么?我应该根据会话中的内容使用枝条扩展来返回WebshopItem对象的价格吗?我是否应该从数据库中过滤WebshopPrices?
期待您的最佳解决方案。谢谢!
实体/ WebshopItem.php
class WebshopItem
{
/**
* @var \Doctrine\Common\Collections\Collection
*/
private $prices;
etc....
}
实体/ WebshopItemPrice.php
class WebshopItemPrice
{
/**
* @var integer
*/
private $id;
/**
* @var string
*/
private $currency;
/**
* @var string
*/
private $price;
private $webshopItem;
}
答案 0 :(得分:1)
<强>更新强>
您也可以使用entity listener,但在这种情况下,您需要覆盖默认解析程序才能在侦听器中获取会话:
<强>的src /你/ GreatBundle /资源/配置/ services.yml 强>
doctrine.orm.default_entity_listener_resolver:
class: Your\GreatBundle\Listener\EntityListenerResolver
arguments: [@service_container]
<强>的src /你/ GreatBundle /监听器/ EntityListenerResolver 强>
namespace Your\GreatBundle\Listener;
use Doctrine\ORM\Mapping\EntityListenerResolver as EntityListenerResolverInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class EntityListenerResolver implements EntityListenerResolverInterface
{
private $instances = [];
private $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function clear($className = null)
{
if ($className === null) {
$this->instances = [];
return;
}
if (isset($this->instances[$className = trim($className, '\\')])) {
unset($this->instances[$className]);
}
}
public function register($object)
{
if ( ! is_object($object)) {
throw new \InvalidArgumentException(sprintf('An object was expected, but got "%s".', gettype($object)));
}
$this->instances[get_class($object)] = $object;
}
public function resolve($className)
{
if (isset($this->instances[$className = trim($className, '\\')])) {
return $this->instances[$className];
}
// Here we are injecting the entire container to the listeners
return $this->instances[$className] = new $className($this->container);
}
}
您可以在使用该用户会话注入的服务中收听Doctrine's postLoad event:
<强>的src /你/ GreatBundle /资源/配置/ services.yml 强>
services:
price.listener:
class: Your\GreatBundle\Listener\PriceListener
arguments: [@session]
tags:
- { name: doctrine.event_listener, event: postLoad }
<强>的src /你/ GreatBundle /监听器/ PriceListener.php 强>
namespace Your\GreatBundle\Listener\PriceListener;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Your\GreatBundle\Entity\WebshopItem;
class PriceListener
{
private $session;
public function __construct(SessionInterface $session)
{
$this->session = $session;
}
public function postLoad(LifecycleEventArgs $event)
{
$entity = $event->getEntity();
if ($entity instanceof WebshopItem) {
$currency = $this->session->get('currency', 'EUR');
$entity->setCurrency(currency);
}
}
}
<强>的src /你/ GreatBundle /实体/ WebshopItem.php 强>
namespace Your\GreatBundle\Entity;
class WebshopItem
{
...
// You don't need to persist this...
private $currency = 'EUR';
public function setCurrency($currency)
{
$this->currency = $currency;
}
public function getPrice()
{
foreach ($this->prices as $price) {
if ($price->getCurrency() === $this->currency) {
return ($price->getPrice();
}
}
return null;
}
}
答案 1 :(得分:0)
您可以查询使用WebshopItemPrice WHERE
WebshopItemPrice.currency = $ variableFromSesion加入的WebshopItem。例如:
$queryBuilder
->select('WebshopItem, WebshopItemPrice')
->leftJoin('WebshopItemPrice.prices', 'WebshopItemPrice')
->where('WebshopItemPrice.currency = :currency')
->setParameter('currency', $variableFromSesion)
其中$variableFromSesion
是会话中存储的当前用户货币。执行该查询后(通过getResult()
),您可以通过调用$ webshopItem-&gt; getPrices()获得价格 - 这应该只返回一个结果
答案 2 :(得分:0)
技巧不是关于如何检索数据,而是关于如何使用它来执行此操作。因为这取决于Request对象,所以你应该使用service-ish。如果你确定你永远不会在其他地方使用它,那么请使用枝条扩展。如果您的后端代码也会使用它,那么请使用服务,例如MyPricePickerService(并在twig扩展中获取)。关于twig扩展的注意事项,我找不到任何保证为每个范围创建新实例的东西,因此每次调用此操作时,都应该使用注入的Container(因此不是缓存的Request或MyPricePickerService的先前实例)! / p>