PHP code example of pechynho / polymorphic-doctrine
1. Go to this page and download the library: Download pechynho/polymorphic-doctrine library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
use Doctrine\ORM\Mapping as ORM;
use Pechynho\PolymorphicDoctrine\Attributes\DynamicPolymorphicProperty;
use Pechynho\PolymorphicDoctrine\Attributes\EntityWithPolymorphicRelations;
use Pechynho\PolymorphicDoctrine\Attributes\ExplicitPolymorphicProperty;
use Pechynho\PolymorphicDoctrine\Contract\PolymorphicValueInterface;
#[ORM\Entity]
#[EntityWithPolymorphicRelations]
class Payment
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[DynamicPolymorphicProperty([
'eshop_item' => EshopItem::class,
'subscription' => Subscription::class,
])]
public PolymorphicValueInterface $dynamicSubject;
#[ExplicitPolymorphicProperty([
'eshop_item' => EshopItem::class,
'subscription' => Subscription::class,
])]
public PolymorphicValueInterface $explicitSubject;
}
class PaymentService
{
public function __construct(
private readonly EntityManagerInterface $em,
private readonly PolymorphicValueFactoryInterface $polymorphicValueFactory,
) {}
public function createPayment(EshopItem $item): void
{
$payment = new Payment();
// Initialize with a value
$payment->dynamicSubject = $this->polymorphicValueFactory->create(
Payment::class, 'dynamicSubject', $item
);
// Initialize as null
$payment->explicitSubject = $this->polymorphicValueFactory->create(
Payment::class, 'explicitSubject'
);
$this->em->persist($payment);
$this->em->flush();
}
}
// With a value
$payment->subject = $this->polymorphicValueFactory->create(Payment::class, 'subject', $entity);
// As null
$payment->subject = $this->polymorphicValueFactory->create(Payment::class, 'subject');
// Set a new value
$payment->subject->update($newEntity);
// Set to null
$payment->subject->setNull();
// or: $payment->subject->update(null);
// Check status
$payment->subject->isNull(); // Is the value null?
$payment->subject->isResolvable(); // Does it have a valid type and ID?
$payment->subject->isLoaded(); // Is the entity already loaded in memory?
// Get the entity (lazy-loaded from DB on first access)
$entity = $payment->subject->getValue();
if ($entity instanceof EshopItem) {
// ...
} elseif ($entity instanceof Subscription) {
// ...
}
// Instead of manual instanceof checks:
$item = $payment->subject->getValueAs(EshopItem::class);
// $item is now typed as EshopItem — full IDE support, no manual narrowing needed
class PaymentService
{
public function __construct(
private readonly EntityManagerInterface $em,
private readonly PolymorphicSearchExprApplierFactoryInterface $applierFactory,
) {}
public function findByEntity(object $entity): array
{
$qb = $this->em->createQueryBuilder()
->select('p')->from(Payment::class, 'p');
$applier = $this->applierFactory->create(Payment::class, 'dynamicSubject', 'p');
$applier->eq($qb, $entity);
return $qb->getQuery()->getResult();
}
public function findByType(string $entityClass): array
{
$qb = $this->em->createQueryBuilder()
->select('p')->from(Payment::class, 'p');
$applier = $this->applierFactory->create(Payment::class, 'explicitSubject', 'p');
$applier->isInstanceOf($qb, $entityClass);
return $qb->getQuery()->getResult();
}
}