【问题标题】:use via with many to many relationship in yii framework在 yii 框架中使用 via 与多对多关系
【发布时间】:2018-08-09 09:25:39
【问题描述】:

我在 yii 上有点挣扎。 我目前正在尝试显示具有多对多关系的数据。

我有:

table set
name
description

table item 
name
description

table subinventory
name
description

and table setDetail who link them all
set_id
item_id
subinventory_id

我为 Set 生成了一个 crud 并添加了一个 Gridview 来显示集合中存在的所有项目(保存在 setDetail 表中) 数据提供者就是这个

$dataProvider= new ActiveDataProvider(
          [ 'query' => $this->hasMany(SetDetail::className(), ['set_id' => 'id'])
        ]

它运行良好,但它当然会显示项目和子库存的 ID。 我可以在 gridview 中检索数据,但它会为每个我认为不理想的数据发出请求。

我想做一个这样的 viaTable:

$dataProvider= new ActiveDataProvider(
              [ 'query' => $this->hasMany(SetDetail::className(), ['set_id' => 'id'])->viaTable('item',['id => 'item_id'])
            ]

但这显然不起作用,因为 item_id 不在 set 表中,而是在 setDetail 表中。

所以我的问题:有没有办法正确(我的意思是使用 yii 框架)使用 viaTable 和查询提供的数据? 我肯定不是很清楚,所以请不要犹豫,纠正我

这里是setDetail模型中生成的关系。

  /**
     * @return \yii\db\ActiveQuery
     */
    public function getItem()
    {
        return $this->hasOne(Item::className(), ['id' => 'item_id']);
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getReason()
    {
        return $this->hasOne(Reason::className(), ['id' => 'reason_id']);
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getReference()
    {
        return $this->hasOne(Reference::className(), ['id' => 'reference_id']);
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getSet()
    {
        return $this->hasOne(Set::className(), ['id' => 'set_id']);
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getSubinventory()
    {
        return $this->hasOne(Subinventory::className(), ['id' => 'subinventory_id']);
    }

【问题讨论】:

  • 您是否使用SetModel 创建dataProvider?然后添加 SetDetail 模型,其中包含所有关系。
  • @InsaneSkull 是的,我在 Set 模型中创建了数据提供者。我很确定我在搞砸它,并且有一种更好的方法可以做到这一点。另外,我可能没有正确完成我想要实现的数据库
  • 该死的,我只是测试了一些没有信念的东西及其工作......

标签: activerecord yii2 many-to-many


【解决方案1】:

我回答我自己的问题,主要是因为我在真正搜索之前问过......

我想使用 via,但我需要一个 leftJoin。另外,我简单地测试了database.column 及其工作。所以我的代码是这样的。

  $dataProvider= new ActiveDataProvider(
      [ 'query' => $this->hasMany(SetDetail::className(), ['set_id' => 'id'])
    ->leftJoin('item','`item`.`id` = `setDetail`.`item_id`')
    ->leftJoin('subinventory','`subinventory`.`id` = `setDetail`.`subinventory_id`')
    ->select([
      "`setDetail`.*",
      "`item`.name AS item_name",
      "`subinventory`.name AS subinventory_name",
    ])
      ]
    );

我还需要在 SetDetail 模型中添加 subinventory_name 和 item_name :

class SetDetail extends \yii\db\ActiveRecord
{
  public $item_name;
  public $subinventory_name;
…

【讨论】:

  • 不需要,添加你的setDetail模型,我会添加更好的解决方案。
  • 您到底需要什么?整个 setDetail 模型文件?
  • @InsaneSkull 这就是你想要的?
【解决方案2】:

你可以试试这样的:

$dataProvider= new ActiveDataProvider([
    'query' => Set::find()->with(['setDetails.item', 'setDetails.subinventory'])->where(['id' => $id]);
]);

这里,setDetails 是您在 Set 模型中的 hasMany 关系名称。

供查看

$model = Set::find()
   ->with(['setDetails.item', 'setDetails.subinventory'])
   ->where(['id' => $id])
   ->one();

setDetails 上使用 foreach 来显示每个 SetDetail 模型。

【讨论】:

  • 您的请求中没有where条件?
  • @eephyne 为什么你需要在哪里?
  • 我可能把我的情况解释得很糟糕。想象以下场景:我进入集合列表,我选择其中一个并进入 /set/view?id=X。在视图页面中,我想显示 set_id = X 的所有 setDetail 行。在此列表中,我想显示子库存和项目的名称。这就是为什么 WHERE 是强制性的(我相信如此)
  • 查看是必须的,这里不需要dataProvider,可以循环遍历setDetail。更新了答案。
  • 是的,但是对于每个 setDetail.* 我会做的,它会发出一个 sql 请求,如果我有 100 行 5 列它会发出 500 个请求,这有点太多了?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-11
  • 1970-01-01
  • 2017-01-28
相关资源
最近更新 更多