Reputation: 542
I have 3 Yii2 ActiveRecord models: Emplpoyee
, Department
and Organization
.
Employee
must have either one Department
or one Organization
, that is ensured by validation (fails if both department_id
and organization_id
are null
or both are not null
). Department
must have one Organization
, it's a standard yii2 ORM relation via hasOne()
.
Gii created this code for employee/organization relation:
class Employee
{
public function getOrganization()
{
return $this->hasOne(app\models\Organization::class, ['id' => 'organization_id']);
}
}
So when I call $employeeObject->organization
, I will get null
if organization_id
in SQL table is null.
I want to modify this standard getter function to return $this->department->organization
in be able to get $employee->organization
via magic getter like this: if an employee has department - organization gets from department, otherwise - via standard relation.
Update: if I write:
/**
* @return ActiveQuery
*/
public function getOrganization()
{
if (!is_null($this->organization_id)) {
return $this->hasOne(app\models\Organization::class, ['id' => 'organization_id']);
} elseif (!is_null($this->department)) {
return $this->department->getOrganization();
} else {
// We should not be here, but what if we are?
}
}
How do I handle a situation of broken relation to Department
or both organization_id
and department_id
is null
? Which ActiveQuery
do I return?
Upvotes: 0
Views: 305
Reputation: 22174
Relations definitions are used to build SQL query for related models. In some cases (eager loading, joins) query needs to be created before you get actual object, so you cannot use if ($this->organization_id)
because $this
is not actual model and $this->organization_id
will alway be null
. The only thing that you can get is to define regular relations without any conditions and getter method (getOrganizationModel()
), which will return correct organization from relations:
class Employee extends ActiveRecord {
public function getDepartment() {
return $this->hasOne(Department::class, ['id' => 'department_id']);
}
public function getOrganization() {
return $this->hasOne(Organization::class, ['id' => 'organization_id']);
}
public function getOrganizationModel() {
if ($this->organization_id !== null) {
return $this->organization;
}
return $this->department->organization;
}
}
class Department extends ActiveRecord {
public function getOrganization() {
return $this->hasOne(Organization::class, ['id' => 'organization_id']);
}
}
Then you can query records with both relations and use getter to get organization:
$employees = Employe::find()->with(['department.organization', 'organization'])->all();
foreach ($employees as $employee) {
echo $employee->getOrganizationModel()->name;
}
Upvotes: 1