Что такое Doctrine-ориентированный подход к работе с репозиториями, которые используют сущности в конфигурации сопоставленного суперкласса?

У меня есть несколько объектов, которые связаны между собой, такие как McDoublePrice, CheeseburgerPrice, BigMacPriceи т. д., которые имеют общее 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
}

Примечание: разные $burgerIds может представлять различные стили бургера в одном и том же типе бургера. то есть, версия Deluxe, обычная версия и т. д. и могут использовать разные конкретные цены для одного и того же типа ингредиентов. то есть обычная булочка против роскошной булочки может иметь разные $ burderID и разные цены на булочки.

Вопрос: Как мне структурировать мой код?

Должен ли я создать один класс хранилища для каждого из BurgerPrice юридическое лицо? Это может создать много дополнительных классов и кажется расточительным.

Могу ли я сойти с рук с одним BurgerRepository класс, который может обрабатывать несколько гамбургеров? Если так, то как бы я изложил это в доктринально-ориентированной манере?

Я ищу пример кода или четкую идею о том, как это сделать. Меня интересует прежде всего Doctrine-ориентированный или Doctrine-рекомендуемый подход к работе с несколькими полиморфными сущностями в конфигурации Mapped Superclass.

Моя конечная цель — иметь возможность запрашивать цену определенных гамбургеров во время выполнения.

Я смотрел в Паттерн Doctrine Entity Repository, и структура репозитория (где я могу создавать собственные имена методов) — это то, что я хотел бы использовать, но пример не показывает, как использовать ее с полиморфными сущностями.

Образцы сущностей

/**
* @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;
}

1

Решение

Не уверен, является ли это подходом, рекомендованным доктриной, или нет, но он кажется мне достаточно конгруэнтным, чтобы я мог определять один репозиторий, но используйте разные случаи этого

На каждой полиморфной сущности я могу следовать шаблону Entity Repository 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());
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]