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
{
}
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 collection 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 fist. To access not shared properties, prepend a class name into the expression path.
$orm->addresses->findBy([
'type' => Address::TYPE_PUBLIC,
'Address->maintainer->id' => $maintainerId,
]);
The relationships itself point to 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.