【问题标题】:Yii2 ORM smart get related modelYii2 ORM智能获取相关模型
【发布时间】:2018-07-08 03:55:40
【问题描述】:

我有 3 个 Yii2 ActiveRecord 模型:EmplpoyeeDepartmentOrganization

Employee 必须有一个Department 或一个Organization,这是通过验证确保的(如果department_idorganization_id 都是null 或两者都不是null,则失败)。 Department 必须有一个Organization,这是通过hasOne() 实现的标准yii2 ORM 关系。

Gii 为员工/组织关系创建了此代码:

class Employee
{
    public function getOrganization()
    {
        return $this->hasOne(app\models\Organization::class, ['id' => 'organization_id']);
    }
}

所以当我调用$employeeObject->organization时,如果SQL表中的organization_id为空,我会得到null

我想修改这个标准的 getter 函数以返回 $this->department->organization,以便能够像这样通过魔术 getter 获得 $employee->organization:如果员工有部门 - 组织从部门获取,否则 - 通过标准关系。

更新:如果我写:

/**
 * @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?
    }
}

我如何处理与Departmentorganization_iddepartment_idnull 的关系中断的情况?我该返回哪个ActiveQuery

【问题讨论】:

  • 那么问题出在哪里?您是否尝试过编写自己的吸气剂?给我们看一些代码。
  • 添加了经验代码。我不明白如何处理破裂的关系?抛出异常?
  • 只返回null。

标签: php orm yii2


【解决方案1】:

关系定义用于为相关模型构建 SQL 查询。在某些情况下(急切加载、连接)查询需要在获得实际对象之前创建,因此您不能使用if ($this->organization_id),因为$this 不是实际模型并且$this->organization_id 将始终是null。您唯一能得到的就是定义没有任何条件的常规关系和 getter 方法 (getOrganizationModel()),它将从关系中返回正确的组织:

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']);
    }
}

然后您可以查询具有两个关系的记录并使用getter来获取组织:

$employees = Employe::find()->with(['department.organization', 'organization'])->all();
foreach ($employees as $employee) {
    echo $employee->getOrganizationModel()->name;
}

【讨论】:

  • 是的。这绝对是一种更好的处理方式。我已经删除了涉及via() 的答案,因为它可以处理更好的连接和急切加载。
  • 这是正确的,虽然完全不优雅,唉。我想知道是否有办法解决@SalemOuerdani 回答的急切加载问题。就像检查我们是否处于急切加载模式和延迟加载杰出模型一样。
  • @SergeAx 如果您不关心预加载和连接,您可以使用带有Organization::findOne($this->organization_id) 和一些内部缓存的常规getter。关系的全部意义在于支持急切加载和加入 - 如果您不需要这些功能,则无需与关系进行斗争。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-04
相关资源
最近更新 更多