乐趣区

关于php:Yii2在多个表之间定义关系的正确方法

在控制器中,我有以下代码:

public function actionView($id)
{
    $query = new Query;
    $query->select('*')
        ->from('table_1 t1')
        ->innerJoin('table_2 t2', 't2.t1_id = t1.id')
        ->innerJoin('table_3 t3', 't2.t3_id = t3.id')
        ->innerJoin('table_4 t4', 't3.t4_id = t4.id')
        ->andWhere('t1.id =' . $id);
    $rows = $query->all();
    return $this->render('view', ['model' => $this->findModel($id),
        'rows' => $rows,
        ]);
}

在视图 view.php 中显示来自 table_2- 4 的数据,这些数据与 table_1 相干:

foreach($rows as $row) {echo $row['t2_field_1'];
    echo $row['t2_field_2'];
    ...
}

它能够工作,然而我不确定这是否是最正确的 Yii2 办法.

我试图在模型 TableOne 中定义关系:

public function getTableTwoRecords()
{return $this->hasMany(TableTwo::className(), ['t1_id' => 'id']);
}
public function getTableThreeRecords()
{return $this->hasMany(TableThree::className(), ['id' => 't3_id'])
    ->via('tableTwoRecords');
}
public function getTableFourRecords()
{return $this->hasMany(TableFour::className(), ['id' => 't4_id'])
    ->via('tableThreeRecords');
}

而后在控制器 TableOneController 中退出记录:

$records = TableOne::find()
    ->innerJoinWith(['tableTwoRecords'])
    ->innerJoinWith(['tableThreeRecords'])
    ->innerJoinWith(['tableFourRecords'])
    ->all(); 

然而它不起作用. 如果我仅退出前三个表,那么它将起作用. 如果增加第四张表,则会收到以下谬误音讯:” 获取未知属性:frontend \ models \ TableOne :: t3_id”

如果我以这种形式更改函数 getTableFourRecords():

public function getTableFourRecords()
{return $this->hasOne(TableThree::className(), ['t4_id' => 'id']);
}

而后我收到此谬误音讯:”SQLSTATE [42S22]: 找不到列:1054’on 子句 ’ 中的未知列 ’table_4.t4_id’ 正在执行的 SQL 是:SELECT table_1 .* FROM table_1 INNER JOIN table_2 ON table_1 . id = table_2 . t1_id INNER JOIN table_3 ON table_2 . t3_id = table_3 . id INNER JOIN table_4 ON table_1 . id = table_4 . t4_id “

解决办法:

Model TableOne:

public function getTableTwoRecords()
    {return $this->hasMany(TableTwo::className(), ['t1_id' => 'id']);
    }

Model TableTwo:

public function getTableThreeRecord()
    {return $this->hasOne(TableThree::className(), ['id' => 't3_id']);
    }

Model TableThree:

public function getTableFourRecord()
{return $this->hasOne(TableFour::className(), ['id' => 't4_id']);
}

Controller TableOneController:

public function actionView($id)
{
    return $this->render('view', ['model' => $this->findModel($id),
    ]);
}

The view table-one/view.php:

foreach ($model->tableTwoRecords as $record) {
    echo 'Table 2 >>';
    echo 'ID:' . $record->id;
    echo 'T1 ID:' . $record->t1_id;
    echo 'T3 ID:' . $record->t3_id;
    echo 'Table 3 >>';
    echo 'ID:' . $record->tableThreeRecord->id;
    echo 'T4 ID:' . $record->tableThreeRecord->t4_id;
    echo 'Table 4 >>';
    echo 'ID:' . $record->tableThreeRecord->tableFourRecord->id;
    echo '<br>';
}

也能够应用基于 GridView 的解决方案.

模型 TableTwo:

foreach ($model->tableTwoRecords as $record) {
    echo 'Table 2 >>';
    echo 'ID:' . $record->id;
    echo 'T1 ID:' . $record->t1_id;
    echo 'T3 ID:' . $record->t3_id;
    echo 'Table 3 >>';
    echo 'ID:' . $record->tableThreeRecord->id;
    echo 'T4 ID:' . $record->tableThreeRecord->t4_id;
    echo 'Table 4 >>';
    echo 'ID:' . $record->tableThreeRecord->tableFourRecord->id;
    echo '<br>';
}

应用 yii 为 TableTwo 模型生成的 TableOneController 中的 actionView 函数已被编辑:

use app\models\TableTwo;
use app\models\TableTwoSearch;
...
public function actionView($id)
{
    $searchModel = new TableTwoSearch(['t1_id' => $id, // the data have to be filtered by the id of the displayed record]);
    $dataProvider = $searchModel->search(Yii::$app->request->queryParams);

    return $this->render('view', ['model' => $this->findModel($id),
         'searchModel' => $searchModel,
         'dataProvider' => $dataProvider,
    ]);
}

以及 views/table-one/view.php 的代码如下:

echo GridView::widget([
    'dataProvider' => $dataProvider,
    'columns' => [
     'id',
     't1_id',
     'tableOneRecord.id',
     't3_id',
     'tableThreeRecord.id',
     'tableThreeRecord.t4_id',
     'tableFourRecord.id',
    ],
]);
退出移动版