PHPackages                             vrok/ref-helper - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. vrok/ref-helper

AbandonedArchivedLibrary[Database &amp; ORM](/categories/database)

vrok/ref-helper
===============

Utilities to support polymorphic associations with Doctrine2 entities

v1.2.0(8y ago)013MITPHPPHP &gt;=7.2CI failing

Since Mar 10Pushed 6y ago1 watchersCompare

[ Source](https://github.com/j-schumann/ref-helper)[ Packagist](https://packagist.org/packages/vrok/ref-helper)[ Docs](https://www.vrok.de/)[ RSS](/packages/vrok-ref-helper/feed)WikiDiscussions master Synced today

READMEChangelog (3)Dependencies (4)Versions (4)Used By (0)

Reference Helper
================

[](#reference-helper)

Library to support polymorphic asssociations with Doctrine 2 in Zend Framework 3.

[![Build Status](https://camo.githubusercontent.com/67317427f98a65793427bf2d8f525cce783adac6fc5d4e5e4134c9a1721429f7/68747470733a2f2f7472617669732d63692e6f72672f6a2d736368756d616e6e2f7265662d68656c7065722e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/j-schumann/ref-helper) [![Coverage Status](https://camo.githubusercontent.com/11cd04a00b20ef70bd9b51fac0b9672069fcf65685e1dd37dc9686d716e0842f/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f6a2d736368756d616e6e2f7265662d68656c7065722f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/j-schumann/ref-helper?branch=master)

Many applications have polymorphic relations where we don't know (and don't want to know in advance) which entities may be assigned to which (e.g. which entity is owned by which). For example a bank account may be owned by an user or an organization, a validation may belong to a bank account or an user.

To support this loose coupling we store the class of the referenced entity and the identifiers forming the primary key (e.g. autoincrement or composite keys) in the referencing entity in separate columns. The referencing entities should be kept simple POPOs, they need to implement `Vrok\References\Entity\HasReferenceInterface`, which is implemented in `Vrok\References\Entity\HasReferenceTrait` for re-use. The interface and trait support multiple references on one entity, for example to reference a creator and an owner.

The `Vrok\References\Service\ReferenceHelper` builds on this principle by providing functions to set and retrieve the referenced entities. The helper also has the ability to restrict references to only one or some targeted classes.

Usage
-----

[](#usage)

### Entity preparation

[](#entity-preparation)

1. Implement the `HasReferenceInterface` on your entity that should store the reference to another object, use `HasReferenceTrait` for simplicity
2. Add one or more references to the entity by defining the `$references`property and `${refName}Class`, `${refName}Identifiers` properties for each reference

```
use Doctrine\ORM\Mapping as ORM;
use Vrok\References\Entity\HasReferenceInterface;
use Vrok\References\Entity\HasReferenceTrait;

/**
 * @ORM\Entity()
 * @ORM\Table(name="sources")
 */
class Source implements HasReferenceInterface
{
    use HasReferenceTrait;

    /**
     * @var array ['refName' => (bool)required, ...]
     */
    protected $references = [
        'nullable' => false,
        'required' => true,
    ];

    /**
     * @var string
     * @ORM\Column(type="string", length=255, nullable=false)
     */
    protected $requiredClass;

    /**
     * @var string
     * @ORM\Column(type="string", length=255, nullable=false)
     */
    protected $requiredIdentifiers;

    /**
     * @var string
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    protected $nullableClass;

    /**
     * @var string
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    protected $nullableIdentifiers;

    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    protected $id;

    public function getId()
    {
        return $this->id;
    }
}
```

Now `nullable` and `required` can store references to any other Doctrine entity.

### Set &amp; get references with the ReferenceHelper

[](#set--get-references-with-the-referencehelper)

Using the `ReferenceHelper` you can now set and fetch references:

```
use Vrok\References\Service\ReferenceHelper;

$refHelper = $services->get(ReferenceHelper::class);
$em = $services->get('Doctrine\ORM\EntityManager');

// the referenced object must have its identifiers (primary key columns) set,
// e.g. be already persisted when using autoincrement ID
$target = $em->getRepository(Target::class)->find(1);

$source = new Source();
$refHelper->setReferencedObject($source, 'required', $target);
$em->persist($source);
$em->flush();
$sourceId = $source->getId();

// later:
$loaded = $em->getRepository(Source::class)->find(sourceId);
$refObject = $refHelper->getReferencedObject($source, 'required');
// $refObject == $target
```

### Restrict reference target classes

[](#restrict-reference-target-classes)

To restrict the ReferenceHelper to allow only one or some classes as targets add something like this to your config:

```
    'reference_helper' => [
        'allowed_targets' => [
            'Entity\Source' => [
                'nullable' => [
                    'Entity\Target',
                ],
            ],
        ],
    ],
```

Now for the reference `nullable` only instances of `Entity\Target`(and child classes) are accepted. Every other reference on `Entity\Source` will still allow every target class. Entity classes not listed in `allowed_targets` accept every target for every reference.

### Querying for entities

[](#querying-for-entities)

Because `${refName}Class` is a separate column from the identifiers we can easily filter for every object referencing an entity of class `Target`:

```
$em = $services->get('Doctrine\ORM\EntityManager');
$list = $em->getRepository(Entity\Source::class)->findBy([
    'requiredClass' => Entity\Target::class,
]);
```

We can also use the `ReferenceHelper` to get the values to filter for usage in a queryBuilder etc:

```
use Vrok\References\Service\ReferenceHelper;

$refHelper = $services->get(ReferenceHelper::class);
$em = $services->get('Doctrine\ORM\EntityManager');

$values = $refHelper->getClassFilterData(Entity\Source::class, 'required', Entity\Target::class);
// $values == ['requiredClass' => 'Entity\Target']

$target = $em->getRepository(Entity\Target::class)->find(1);
$values = $refHelper->getEntityFilterData(Entity\Source::class, 'required', $target);
// $values == ['requiredClass' => 'Entity\Target', 'requiredIdentifiers' => '{"id":1}']

$values = $refHelper->getEntityFilterData(Entity\Source::class, 'required', null);
// $values == ['requiredClass' => null, 'requiredIdentifiers' => null]

// add filter to a QueryBuilder:
$qb = $em->getRepository(Entity\Source::class)->createQueryBuilder('s');
$whereClause = [];
foreach ($values as $column => $value) {
    $whereClause[] = "s.$column = :$column';
    $qb->setParameter($column, $value);
}
$qb->andWhere(implode(' AND ', $whereClause));
```

The ReferenceHelper can not add the conditions to a given QueryBuilder for you because it would have to know the alias to use (e.g. if you are using joins) and wether to to combine with previous conditions using "AND" or "OR". Maybe you even want to search for multiple conditions at once:

```
SELECT * FROM Entity\Source s WHERE s.deleted = 0 AND (s.requiredClass = 'Entity\Target'
  OR s.requiredClass = 'Entity\OtherTarget')
```

###  Health Score

26

—

LowBetter than 43% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity5

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity60

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~8 days

Total

3

Last Release

2967d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/ed9373b6806c33f512ca3b63214dd2a2b2621bcbddffcdb99acc66ae7f0324aa?d=identicon)[j-schumann](/maintainers/j-schumann)

---

Top Contributors

[![j-schumann](https://avatars.githubusercontent.com/u/114239?v=4)](https://github.com/j-schumann "j-schumann (13 commits)")

---

Tags

doctrineentitiespolymorphicassociations

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/vrok-ref-helper/health.svg)

```
[![Health](https://phpackages.com/badges/vrok-ref-helper/health.svg)](https://phpackages.com/packages/vrok-ref-helper)
```

###  Alternatives

[hounddog/doctrine-data-fixture-module

Zend Framework 2 Module that provides Doctrine Data-Fixture functionality

37335.4k9](/packages/hounddog-doctrine-data-fixture-module)[mamuz/mamuz-blog

Provides blog feature for ZF2 with Doctrine

101.1k1](/packages/mamuz-mamuz-blog)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
