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/ */

    

pechynho / polymorphic-doctrine example snippets


return [
    // ...
    Pechynho\PolymorphicDoctrine\PechynhoPolymorphicDoctrineBundle::class => ['all' => true],
];

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();
    }
}

$builder = $this->builderFactory->create(Payment::class, 'dynamicSubject', 'p');

$eqResult = $builder->eq($item);
$instanceOfResult = $builder->isInstanceOf(EshopItem::class);

$qb->where($qb->expr()->orX($eqResult->expr, $instanceOfResult->expr));

foreach ([$eqResult, $instanceOfResult] as $result) {
    foreach ($result->params as $key => $value) {
        $qb->setParameter($key, $value);
    }
}

#[ExplicitPolymorphicProperty([
    'product' => Product::class,
    'service' => [
        'fqcn' => Service::class,
        'idProperty' => 'serviceId',
        'onDelete' => 'CASCADE',
    ],
])]
public PolymorphicValueInterface $subject;
bash
php bin/console pechynho:polymorphic-doctrine:generate-reference-classes