Spiral ORM and loading mechanism does not limit you in how to build your hierarchies, though it is important to remember basic aspects of how to work with such models.
We can define model which belongs to itself following way:
class Recursive extends RecordEntity
{
const SCHEMA = [
'id' => 'bigPrimary',
'name' => 'string',
'parent' => [
self::BELONGS_TO => self::class,
self::NULLABLE => true,
self::CREATE_CONSTRAINT => false
],
];
}
It is important to mark your relation as nullable.
You are able to use table FK constrains, however some DBMS (SQLServer) forbid CASCADE behaviour of recursive data.
Nesed hierarchy works as any other relation:
$recursive = new Recursive();
$recursive->parent = $recursive_a = new Recursive();
$recursive_a->parent = $recursive_b = new Recursive();
$recursive_b->parent = $recursive_c = new Recursive();
$recursive->save();
We can use load
and with
of our RecordSelector to load (join) any level of relation:
//Only models with 3 level of parents
$recursive = $this->orm->selector(Recursive::class)->with('parent.parent.parent')->findOne();
At this moment, Spiral ORM is not capable to properly save self referenced models, i.e. such constuctions will fail:
$recursive = new Recursive();
$recursive->parent = $recursive;
$recursive->save();
Though, it is possible to load such data from ORM by disabling entity map.
$recursive = $this->orm->withMap(null)->selector(Recursive::class)
->with('parent.parent.parent')
->findOne();
Attention, with disabled map you have a chance to get multiple models represent same row in database!