根据会话值选择实体

时间:2014-04-22 20:14:00

标签: php symfony

我有两个实体。一个是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;
}

3 个答案:

答案 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>