1

我有几个相关的实体,例如McDoublePriceCheeseburgerPriceBigMacPrice等,它们在Mapped Superclass Doctrine 配置中具有公共BurgerPrice实体。

如何从我的控制器、操作或请求处理程序访问特定实体?也就是说,我希望以下代码工作:

$burgers = array(
    'McDoublePrice' => 4,
    'CheeseburgerPrice' => 5, 
    'BigMacPrice' => 6
);
foreach($burgers as $burger => $burgerId)
{
    $repository = $this->repositoryFactory->getBurgerRepository($burger);
    $entity = $repository->getBurgerEntity($burgerId);
    echo $entity->getBurgerPrice(); // total price of current burger
}

注意:不同$burgerId的 s 可以代表同一种汉堡中不同的汉堡风格。即豪华版,普通版等,并且可以对相同类型的成分使用不同的具体价格。即普通包子和豪华包子可以有不同的$burderID和不同的包子定价。

问题:如何构建我的代码?

我是否为每个BurgerPrice实体创建一个存储库类?这可能会创建很多额外的课程,而且看起来很浪费。

我可以通过一个BurgerRepository可以处理多个汉堡的课程逃脱吗?如果是这样,我将如何以以教义为中心的方式进行设置?

我正在寻找代码示例或有关如何执行此操作的清晰想法。我主要对以 Doctrine 为中心或 Doctrine 推荐的方法来处理映射超类配置中的多个多态实体感兴趣。

我的最终目标是能够在运行时请求特定汉堡的定价。

我已经研究了Doctrine Entity Repository pattern,并且我想使用存储库结构(我可以在其中创建自定义方法名称),但是该示例没有显示如何将它与多态实体一起使用。

示例实体

/**
 * @ORM\Entity(repositoryClass="BurgerPriceRepository")
 * @Table(name="bigmac", indexes={@Index(name="product_id", columns={"product_id"})})
 * @Entity
 */
class BigMacPrice extends BurgerPrice
{
    /** @var float @Column(name="sauce", type="decimal", precision=6, scale=2, nullable=false) */
    private $sauce;

    function getBurgerPrice(): float
    {
        //secret sauce price
        return 5 * $this->patty + 3 * $this->bun + $this->sauce;
    }
}

/**
 * @ORM\Entity(repositoryClass="BurgerPriceRepository")
 * @Table(name="mcdouble", indexes={@Index(name="product_id", columns={"product_id"})})
 * @Entity
 */
class McDoublePrice extends BurgerPrice
{
    function getBurgerPrice(): float
    {
        //a different price for mcdouble
        return 2 * $this->patty + 2 * $this->bun;
    }
}

abstract class BurgerPrice
{
    /** @var integer @Column(name="id", type="integer", nullable=false) @Id @GeneratedValue(strategy="IDENTITY") */
    protected $id;

    /** @var integer @Column(name="product_id", type="integer", nullable=false) */
    protected $productId;

    /** @var float @Column(name="patty", type="decimal", precision=6, scale=2, nullable=false) */
    public $patty;

    /** @var float @Column(name="bun", type="decimal", precision=6, scale=2, nullable=false) */
    public $bun;

    /**
     * Computes specific product price for a given burger
     *
     * @return float
     */
    abstract function getBurgerPrice(): float;
}
4

1 回答 1

0

不确定这是否是 Doctrine 推荐的方法,但对我来说似乎足够一致,我可以定义一个存储库但使用它的不同实例

在每个多态实体上,我可以遵循 Doctrine 的实体存储库模式,并指定

@ORM\Entity(repositoryClass="BurgerPriceRepository")

虽然如果我不包括那条线似乎没有什么区别。也许它在其他地方很方便。

然后我可以使用这些类:

class BurgerPriceRepositoryFactory
{

    /**@var EntityManager*/
    private $entityManager;

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

    function getRepository(string $entityName): BurgerPriceRepository
    {
        return new BurgerPriceRepository(
            $this->entityManager, 
            new ClassMetadata($entityName)
        );
    }
}

class BurgerPriceRepository extends EntityRepository
{

    function getBurgerPriceEntity(int $burgerId): BurgerPrice
    {
        return $this->getEntityManager()
            ->getRepository($this->_entityName)
            ->findOneBy(array(
            'productId' => $burgerId
        ));
    }
}

然后像这样在我的测试中使用它们:

/** @var ContainerInterface $container */
/* Service-creation time */
$factory = new ProductPricingRepositoryFactoryFactory();
$this->repositoryFactory = $factory($container);

/* Run-time - Big Mac */
$repository = $this->repositoryFactory->getRepository(BigMacPrice::class);
$entity = $repository->getBurgerPriceEntity($bigMacId);
$this->assertEquals(3.57, $entity->getBurgerPrice());

/* Run-time - McDouble*/
$repository = $this->repositoryFactory->getRepository(McDoublePrice::class);
$entity = $repository->getBurgerPriceEntity($mdDoubleId);
$this->assertEquals(1.39, $entity->getBurgerPrice());
于 2018-02-22T19:21:13.830 回答