Yii2 在网格中加入 6 个表 + 下拉过滤器
Yii2 join 6 tables + dropdown filter in grid
我有以下tables/models:A、B、C、BC、D、BCD
(A:B 1:N) table D转BCD就没问题了。但是,我想将关键属性过滤为 A、B、C 和 D 的下拉列表,以在 BCD 中查找结果(因为最后我需要 BCDid)。在 BCid 和 Did 旁边的 BCD 中,我当然可以存储 Aid、Bid 和 Cid,在我看来这似乎是一个很简单的解决方法,但我知道这完全反对数据库规范化。还有另一种更好的方法(当然是急切加载)吗?
我现在在 BCD 中有这个:
public function getB() {
return $this->hasOne(\app\models\B::className(), ['id' => 'Bid'])
->via('BC');
}
它似乎可以工作,但不是急于加载。
我如何到达模型 A?我可以在 BCD 中这样定义它吗?:
public function getA() {
return $this->hasOne(\app\models\A::className(), ['id' => 'Aid'])
->via('BC')
->via(B);
}
还没有真正起作用。
这种工作方式 (BCSearch):
public function search($params) {
$query = BC::find()->joinWith('A', true)->joinWith('C', true);
BC 中的关系 A 用 "via" 定义。下拉过滤器也有效。
但是我仍然不知道如何在数据库结构中更深入地实现一个层次。
这种方式似乎完全有效:
models/BCDSearch.php
public function search($params) {
$query = BCD::find()
->select([
'BCD.id',
'BCD.amount',
'A.id AS A_Id',
'A.name AS A_name',
'B.name AS B_name',
'B.name2 AS B_name2',
'C.name AS C_name',
'D.name AS D_name',
])
->leftJoin('BC', 'BC.id = BC_Id')
->leftJoin('B', 'B.id = B_Id')
->leftJoin('A', 'A.id = A_Id')
->leftJoin('C', 'C.id = C_Id')
->leftJoin('D', 'D.id = D_Id');
$query->andFilterWhere([
...
'A.id' => $this->A_Id,
'B.name' => $this->B_name,
'B.name2' => $this->B_name2,
'C.name' => $this->C_name,
'D.name' => $this->D_name,
]);
public function rules() {
return [
...
[[... 'A_Id', 'B_name', 'B_name2', 'C_name', 'D_name'], 'safe'],
];
}
models/base/BCD.php:
class BCD extends Whatever {
public $A_Id;
public $A_name;
public $B_name;
public $B_name2;
public $C_name;
public $D_name;
views/BCD/index.php:
GridView::widget([
'layout' => '{summary}{pager}{items}{pager}',
'dataProvider' => $dataProvider,
'pager' => [
'class' => yii\widgets\LinkPager::className(),
'firstPageLabel' => Yii::t('app', 'First'),
'lastPageLabel' => Yii::t('app', 'Last')],
'filterModel' => $searchModel,
'columns' => [
[
'attribute' => 'A_Id',
'value' => 'A_name',
'filter' => yii\helpers\ArrayHelper::map(app\models\A::find()->all(), 'id', 'name')
],
[
'attribute' => 'B_name',
'value' => 'B_name',
'filter' => yii\helpers\ArrayHelper::map([['id' => 'name1', 'name' => 'name1'], ['id' => 'name2', 'name' => 'name2']], 'id', 'name')
],
[
'attribute' => 'B_name2',
'value' => 'B_name2',
'filter' => yii\helpers\ArrayHelper::map([['id' => 'name2_1', 'name' => 'name2_1'], ['id' => 'name2_2', 'name' => 'name2_2']], 'id', 'name')
],
[
'attribute' => 'C_name',
'value' => 'C_name',
'filter' => yii\helpers\ArrayHelper::map(app\models\C::find()->all(), 'C_name', 'C_name')
],
[
'attribute' => 'D_name',
'value' => 'D_name',
'filter' => yii\helpers\ArrayHelper::map(app\models\D::find()->all(), 'D_name', 'D_name')
],
'amount',
...
希望这对其他人有所帮助。找出这个基本简单的解决方案并不容易(至少对我而言)。我不知道为什么,但到目前为止我在网上找不到任何相关信息。
我有以下tables/models:A、B、C、BC、D、BCD
(A:B 1:N) table D转BCD就没问题了。但是,我想将关键属性过滤为 A、B、C 和 D 的下拉列表,以在 BCD 中查找结果(因为最后我需要 BCDid)。在 BCid 和 Did 旁边的 BCD 中,我当然可以存储 Aid、Bid 和 Cid,在我看来这似乎是一个很简单的解决方法,但我知道这完全反对数据库规范化。还有另一种更好的方法(当然是急切加载)吗? 我现在在 BCD 中有这个:
public function getB() {
return $this->hasOne(\app\models\B::className(), ['id' => 'Bid'])
->via('BC');
}
它似乎可以工作,但不是急于加载。 我如何到达模型 A?我可以在 BCD 中这样定义它吗?:
public function getA() {
return $this->hasOne(\app\models\A::className(), ['id' => 'Aid'])
->via('BC')
->via(B);
}
还没有真正起作用。
这种工作方式 (BCSearch):
public function search($params) {
$query = BC::find()->joinWith('A', true)->joinWith('C', true);
BC 中的关系 A 用 "via" 定义。下拉过滤器也有效。 但是我仍然不知道如何在数据库结构中更深入地实现一个层次。
这种方式似乎完全有效:
models/BCDSearch.php
public function search($params) {
$query = BCD::find()
->select([
'BCD.id',
'BCD.amount',
'A.id AS A_Id',
'A.name AS A_name',
'B.name AS B_name',
'B.name2 AS B_name2',
'C.name AS C_name',
'D.name AS D_name',
])
->leftJoin('BC', 'BC.id = BC_Id')
->leftJoin('B', 'B.id = B_Id')
->leftJoin('A', 'A.id = A_Id')
->leftJoin('C', 'C.id = C_Id')
->leftJoin('D', 'D.id = D_Id');
$query->andFilterWhere([
...
'A.id' => $this->A_Id,
'B.name' => $this->B_name,
'B.name2' => $this->B_name2,
'C.name' => $this->C_name,
'D.name' => $this->D_name,
]);
public function rules() {
return [
...
[[... 'A_Id', 'B_name', 'B_name2', 'C_name', 'D_name'], 'safe'],
];
}
models/base/BCD.php:
class BCD extends Whatever {
public $A_Id;
public $A_name;
public $B_name;
public $B_name2;
public $C_name;
public $D_name;
views/BCD/index.php:
GridView::widget([
'layout' => '{summary}{pager}{items}{pager}',
'dataProvider' => $dataProvider,
'pager' => [
'class' => yii\widgets\LinkPager::className(),
'firstPageLabel' => Yii::t('app', 'First'),
'lastPageLabel' => Yii::t('app', 'Last')],
'filterModel' => $searchModel,
'columns' => [
[
'attribute' => 'A_Id',
'value' => 'A_name',
'filter' => yii\helpers\ArrayHelper::map(app\models\A::find()->all(), 'id', 'name')
],
[
'attribute' => 'B_name',
'value' => 'B_name',
'filter' => yii\helpers\ArrayHelper::map([['id' => 'name1', 'name' => 'name1'], ['id' => 'name2', 'name' => 'name2']], 'id', 'name')
],
[
'attribute' => 'B_name2',
'value' => 'B_name2',
'filter' => yii\helpers\ArrayHelper::map([['id' => 'name2_1', 'name' => 'name2_1'], ['id' => 'name2_2', 'name' => 'name2_2']], 'id', 'name')
],
[
'attribute' => 'C_name',
'value' => 'C_name',
'filter' => yii\helpers\ArrayHelper::map(app\models\C::find()->all(), 'C_name', 'C_name')
],
[
'attribute' => 'D_name',
'value' => 'D_name',
'filter' => yii\helpers\ArrayHelper::map(app\models\D::find()->all(), 'D_name', 'D_name')
],
'amount',
...
希望这对其他人有所帮助。找出这个基本简单的解决方案并不容易(至少对我而言)。我不知道为什么,但到目前为止我在网上找不到任何相关信息。