我得到了两个实体。一个是WebshopItem实体,另一个是WebshopPrice实体。每次创建一个网店商品时,您还需要填写3个网店价格。网店价格为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;
}
更新
您也可以使用实体侦听器,但在这种情况下,您需要覆盖默认的解析器才能在侦听器中获取会话:
src/Your/GreatBundle/Resources/config/services.yml
doctrine.orm.default_entity_listener_resolver:
class: Your'GreatBundle'Listener'EntityListenerResolver
arguments: [@service_container]
src/Your/GreatBundle/Listener/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的postLoad事件:
src/Your/GreatBundle/Resources/config/services.yml
services:
price.listener:
class: Your'GreatBundle'Listener'PriceListener
arguments: [@session]
tags:
- { name: doctrine.event_listener, event: postLoad }
src/Your/GreatBundle/Listener/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/Your/GreatBundle/Entity/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;
}
}
您可以查询加入WebshopItemPrice WHERE
WebshopItemsPrice.current=$variableFromSesion的WebshopItem。例如:
$queryBuilder
->select('WebshopItem, WebshopItemPrice')
->leftJoin('WebshopItemPrice.prices', 'WebshopItemPrice')
->where('WebshopItemPrice.currency = :currency')
->setParameter('currency', $variableFromSesion)
其中,$variableFromSesion
是存储在会话中的当前用户货币。执行该查询后(通过getResult()
),您可以通过调用$webshopItem->getPrices()来获取价格-这应该只返回一个结果
诀窍不在于如何检索数据,而在于用什么来检索数据。因为这取决于Request对象,所以应该使用类似服务的东西。如果你确信你永远不会在其他地方使用这个,那么就使用树枝扩展。如果你的后端代码也会使用它,那么就使用一个服务,比如MyPricePickerService(并在树枝扩展中获取)。请注意,关于trick扩展,我找不到任何可以保证为每个作用域创建新实例的东西,所以在每次调用此操作时,您应该使用注入的Container(所以不是缓存的Request或MyPricePickerService的以前实例)!