Orm supports single-table-inheritance to provide more advanced architecture. Although Orm supports this feature, we still see this design as quite rare and should not be overused or misused.
getEntityClassNames()
. The common abstract entity has to be registered as the first one.Repository::getEntityClassName(array $data)
to detect the entity class name for the specific row.Let’s take a look at example:
/** * @property int $id {primary} * @property string $type {enum self::TYPE_*} */ abstract class Address extends Nextras\Orm\Entity\Entity { const TYPE_PUBLIC = 'public'; const TYPE_PRIVATE = 'private'; } class PrivateAddress extends Address { } /** * @property Maintainer $maintainer {m:1 Maintainer::$addressees} */ class PublicAddress extends Address { } /** * @extends Nextras\Orm\Repository\Repository<Address> */ class AddressesRepository extends Nextras\Orm\Repository\Repository { public static function getEntityClassNames(): array { return [Address::class, PrivateAddress::class, PublicAddress::class]; } public function getEntityClassName(array $data): string { return $data['type'] === Address::TYPE_PUBLIC ? PublicAddress::class : PrivateAddress::class; } }
Collection calls will by default return a mixed result – with both types. You may filter these collections by the common properties defined on the abstract class. If you want to filter by property that is not shared between all entities, it’s your responsibility to filter the proper entities first. To access non-shared properties, prepend a class name with double colon into the expression path.
$orm->addresses->findBy([ 'type' => Address::TYPE_PUBLIC, 'PublicAddress::maintainer->id' => $maintainerId, ]);
The relationship itself point to a specific entity name, so the filtering expression will be evaluated deterministically. Only the starting class name has to be defined, if the property is not shared.