Yii 2:同一张表的多重关系

Posted

技术标签:

【中文标题】Yii 2:同一张表的多重关系【英文标题】:Yii 2: multiple relation with same table 【发布时间】:2015-12-26 06:00:22 【问题描述】:

我在使用 Yii 2 关系表时遇到了问题。我的工作有很多关系,但只有在这种情况下才返回错误:

SQLSTATE[42S22]:找不到列:1054 'where 子句'中的未知列'father.name'

我认为问题在于同一个表“代理”的双重关系。查看模型中的一段代码:

public function getAgent()

    return $this->hasOne(Agent::className(), ['id' => 'id_agent']);

public function getFather()

    return $this->hasOne(Agent::className(), ['id' => 'id_father']);

在我的 GridView 中,我看到了正确的值,但是当我尝试使用 ORDER 或“andWhere”进行过滤时,Yii2 会返回错误。

您可以在下面找到 searchModel 的代码:

$dataProvider->sort->attributes['agentName'] = [ 
        'asc' => ['agent.name' => SORT_ASC],
        'desc' => ['agent.name' => SORT_DESC],
        'default' => SORT_ASC
    ];

$dataProvider->sort->attributes['fatherName'] = [
        //'asc' => ['father.name' => SORT_ASC],
        //'desc' => ['father.name' => SORT_DESC],
        'default' => SORT_ASC
    ];
//.......
$query->andFilterWhere(['like', 'agent.name', $this->agentName]);
$query->andFilterWhere(['like', 'father.name', $this->fatherName]);

agentName 属性工作正常。 有什么建议吗? 谢谢!

-------更新:更多代码--------- 搜索模型:

public function search($params)

    $agent_aux = new Agent();
    $agent_id= $agent_aux->getAgentIdFromUser();

    if (Yii::$app->user->can('admin'))
        $query = Contract::find();
    
    else

        $query = Contract::find()->where(['contract.agent_id' => $agent_id]);            
    

    $query->joinWith(['agent','seminar']);

    $dataProvider = new ActiveDataProvider([
        'query' => $query,
    ]);
    $this->load($params);
    $dataProvider->sort->attributes['seminar_location'] = [
        'asc' => ['seminar.location' => SORT_ASC],
        'desc' => ['seminar.location' => SORT_DESC],
    ];
    $dataProvider->sort->attributes['agentName'] = [ 
        'asc' => ['agent.name' => SORT_ASC],
        'desc' => ['agent.name' => SORT_DESC],
        'default' => SORT_ASC
    ];

    $dataProvider->sort->attributes['fatherName'] = [
        //'asc' => ['father.name' => SORT_ASC],
        //'desc' => ['father.name' => SORT_DESC],
        'default' => SORT_ASC
    ];
    if (!$this->validate()) 
        return $dataProvider;
    
    $query->andFilterWhere([
        'id' => $this->id,
        'data' => $this->data,
        'id_agent' => $this->id_agent,
        'id_father' => $this->id_father,
        'id_seminar' => $this->id_seminar,
    ]);
    $query->andFilterWhere(['like', 'agent.name', $this->agentName]);
    $query->andFilterWhere(['like', 'father.name', $this->fatherName]);
    return $dataProvider;

【问题讨论】:

可能是您拼错了列名。 @InsaneSkull 如果我使用“代理”作为列名(现在我使用“父亲”,即关系的名称),搜索会过滤具有第一个关系(代理)的数据:/ 你有 $query->with(['agent', 'father']) 或类似的行吗?你能显示查询的完整来源吗? @robsch 我有“$query->joinWith(['agent']);” .... 如果我使用“$query->joinWith(['agent','father']);” yii 2 返回 PDOException: SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'agent' 您能提供更多代码并显示表格定义吗? Here 是一个类似的问题。不确定这是否与您的问题相同。但是请看一下。使用 with(...) 不合适吗?我会假设你必须使用两个连接。 【参考方案1】:

@FidoXLNC 答案的替代方法可能是在您进行连接时定义别名:

$query->joinWith([
    'seminar', 
    'agent'  => function ($q)  $q->from(Agent::tableName() . ' agent' ); ,
    'father' => function ($q)  $q->from(Agent::tableName() . ' father'); 
]);

但是 AFAIK 您必须指定两种关系,而不仅仅是一个。

【讨论】:

【参考方案2】:

您需要对模型进行以下更改。 from 子句实际上是在创建一个别名。代理和父关系将在单独的连接子句中选择。在过滤条件中使用“代理”和“父亲”别名和列名。

public function getAgent()

    return $this->hasOne(Agent::className(), ['id' => 'id_agent'])->from(['agent' => Agent::tableName()]);


public function getFather()

    return $this->hasOne(Agent::className(), ['id' => 'id_father'])->from(['father' => Agent::tableName()])

另一个需要改变的是

$query->joinWith(['agent','seminar', 'father']);

【讨论】:

以上是关于Yii 2:同一张表的多重关系的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 定义同一张表的多对多关系

Yii2 过滤具有多重关系的数据

Laravel 对同一张表的两次引用

表与表的关系

Mysql:一个表的一个字段与另一个表的两个字段之间的多重关系

Php Yii 与联结表的关系