[英]Can't Sort HasMany Relationship in Yii2
我知道关于 Yii2 中的排序属性有很多问题。 我是使用这个框架的初学者,我已经用尽了所有可以在互联网上找到的参考资料。
所以对于第一部分。
我尝试在 Controller 上使用 orderBy 方法,但似乎也无法正常工作。
我的 controller 零件使用以下代码:
$saleModel = Sales::find()->with([
'customer',
'salesItems',
'salesItems.item'
])->where(['id' => $id])->one();
现在我在这个 model 上有一个名为 Sales 的 Model 我与 SalesItems model 有很多关系。
public function getSalesItems()
{
return $this->hasMany(SalesItems::className(), ['sale_id' => 'id'])
}
我已经尝试使用可以在此 Model 中找到的“item_id”对该 SalesItems model 进行排序,并且它正在工作。
public function getSalesItems()
{
return $this->hasMany(SalesItems::className(), ['sale_id' => 'id'])
->orderBy(['item_id' => SORT_DESC]);
}
但我想要的是通过另一个连接的表/模型对我的 SalesItems 进行排序,该表/模型通过销售项目 model 中的 item_id 列连接。
在这种情况下,我有另一个名为 items 的表,它有一个 ID 列,这部分是他们加入['id' =>'item_id']
地方。
总的来说,我想根据 items.name 对我的 SalesItems 进行排序。
我的 SQL 语句应该是这样的:
SELECT sales.id , sales.customer_id, sales_items.item_id,
sales_items.sale_id, items.name FROM sales
INNER JOiN sales_items ON sales_items.sale_id = sales.id
INNER JOIN items ON sales_items.item_id = items.id WHERE sales.id =6374
ORDER BY items.name ASC;
我在 DB 上运行此 SQL 语句,并以我想要的方式成功检索结果。
这也是表模式:
希望有人能理解我一直在努力做的事情。
谢谢
你需要使用以下查询与joinWith
来实现你想要的,你需要在列表中再选择一列i.id
否则它只会显示一个项目。
$saleModel = Sales::find()->alias('s')
->select('s.id, s.customer_id, si.item_id, si.sale_id, i.name, i.id')
->joinWith(
[
'customer c',
'salesItems si',
'salesItems.item i'
], false, 'INNER JOIN'
)
->where(['s.id' => 1])->orderBy('i.name ASC')->asArray()->all();
您可以尝试使用ActiveQuery的viaTable函数:
public function getSalesItems()
{
return $this->hasMany(SalesItems::className(), ['sale_id' => 'id'])
->viaTable('items', ['id' => 'item_id'])
->orderBy(['items.name' => SORT_ASC]);
}
试试这些代码(他们在我的localhost上工作):
在控制器中:
$sales = Sales::find()->with([
'customer',
'salesItems',
'salesItems.item'
])->where(['id' => 2])->asArray()->one();
要么
$db = Yii::$app->db;
$query = $db->createCommand("SELECT sales.id , sales.customer_id, sales_items.item_id,
sales_items.sale_id, items.name FROM sales
INNER JOiN sales_items ON sales_items.sale_id = sales.id
INNER JOIN items ON sales_items.item_id = items.id WHERE sales.id =2
ORDER BY items.name ASC;")->queryAll();
在SalesItems模型中:
<?php
//...
class SalesItems extends \yii\db\ActiveRecord
{
//...
public function getItem()
{
return $this->hasOne(Items::className(), ['id' => 'item_id']);
}
//...
}
在销售模型中:
<?php
//...
class Sales extends \yii\db\ActiveRecord
//...
public function getSalesItems()
{
return $this->hasMany(SalesItems::className(), ['sale_id' => 'id'])->orderBy(['item_id' => SORT_DESC]);
}
public function getCustomer()
{
return $this->hasOne(Customers::className(), ['id' => 'customer_id']);
}
// ...
}
使用活动记录:
$query = Sales::find()->alias('sl')
->select('sl.id, sl.customer_id, si.item_id, si.sale_id, itm.name')
->joinWith('salesItem AS si', true)
->joinwith('salesItem.item AS itm')
->where(['si.id' => $id])
->orderBy(['itm.name' => SORT_ASC]);
然后,您可以使用任何提供的方法来检索查询结果。 或者如果您想测试您的查询使用:
$sql = $query->createCommand()->sql;
查看它是否与原始查询匹配。
我很少在大多数框架中使用关系功能,除了laravel,这限制了这个功能。
了解您提出的问题和ERD,我将为此特定问题建议一个简化的答案
我注意到si.sale_id
连接到s.id
,因此在数值上等于保持关系
因此,这是我的首选解决方案
/**
*
* @param integer $sales_id sales id
* @return \frontend\models\SalesItems[] models
*/
public function getSalesItems($sales_id) {
$s = \frontend\models\Sales::tableName();
$si = \frontend\models\SalesItems::tableName();
$i = \frontend\models\Items::tableName();
return $this
->select('s.id, s.customer_id, si.item_id, si.sale_id, i.name')->from("$si si")
->leftJoin("$s s", "'$sales_id' = s.id")
->leftJoin("$i i", "si.item_id = i.id")
->where("si.sale_id = '$sales_id'")
->orderBy('i.name asc')
->all();
}
在SalesItems模型类中运行它
请仅在SalesItems
模型类中引入以下两个属性(不是数据库表表),如下所示
class SalesItems extends \yii\db\ActiveRecord {
// copy line below into SalesItems class
public $name, $customer_id;
}
我相信它是这样高度优化的
希望能帮助到你
谢谢
我知道你问这个问题已经很久了。 我认为 1:n 关系的排序需要完成一些工作,或者它有一些我们无法发现的秘密。 我希望在 yii3 上它会得到解决。
但是对于您的问题,我复制了对您来说很常见的代码。 {{{{信息:我的规范值属于汽车轮胎参数}}}}
我有 1:n 关系( product_tbl 1:n productSpecificationValue_tbl() )每个产品都有很多规格,每个规格都有价值。 我想在 SPECIFICATION_VALUES 中排序我的 gridView
所以我为我想按它排序的每一个规范值编写单独的关系。 我需要其中的 3 个,所以我写了这 3 个关系:
<?php
public function getProductTreadWidth()
{
return $this->hasOne(ProductSpecification::className(), ['product_id' => 'product_id'])->where(['specification_id' => 2]);
}
public function getProductAspectRatio()
{
return $this->hasOne(ProductSpecification::className(), ['product_id' => 'product_id'])->where(['specification_id' => 3]);
}
public function getProductDiameter()
{
return $this->hasOne(ProductSpecification::className(), ['product_id' => 'product_id'])->where(['specification_id' => 5]);
}
?>
然后我获取 GET['sort'] 参数值,如果它是 productTreadWith 我让我的 DataProvider 加入到那个,如果它是 productAspectRatio 我让我的 DataProvider 加入到那个等等......就像下面的代码:
if(Yii::$app->request->get()['sort'] == 'productTreadWidth.value_en' || Yii::$app->request->get()['sort'] == '-productTreadWidth.value_en') {
$joinTable = 'productTreadWidth';
} elseif(Yii::$app->request->get()['sort'] == 'productAspectRatio.value_en' || Yii::$app->request->get()['sort'] == '-productAspectRatio.value_en') {
$joinTable = 'productAspectRatio';
} elseif(Yii::$app->request->get()['sort'] == 'productDiameter.value_en' || Yii::$app->request->get()['sort'] == '-productDiameter.value_en') {
$joinTable = 'productDiameter';
} else {
$joinTable = 'productSpecificationsValuesIndexBySpecificationId';
}
$dataProvider = new ActiveDataProvider([
'query' => Product::find()->joinWith(['brand', 'family', $joinTable ], true, 'LEFT JOIN')->where(['availability_id' => 1]),
]);
$dataProvider->setSort([
'attributes' => [
'productTreadWidth.value_en' => [
'asc' => ['value_en' => SORT_ASC],
'desc' => ['value_en' => SORT_DESC],
'label' => 'Tread Width',
],
'productAspectRatio.value_en' => [
'asc' => ['value_en' => SORT_ASC],
'desc' => ['value_en' => SORT_DESC],
'label' => 'Aspect Ratio',
],
'productDiameter.value_en' => [
'asc' => ['value_en' => SORT_ASC],
'desc' => ['value_en' => SORT_DESC],
'label' => 'Diameter',
],
],
]);
对于 gridView 我使用以下属性:
<?php
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
[
'attribute' => 'brand.name_en',
'label' => 'Brand'
],
[
'attribute' => 'family.name_en',
'label' => 'Model',
],
[
'attribute' => 'productTreadWidth.value_en',
'label' => Yii::t('app' , 'Tire Width'),
'content' => function($model){
return $model->productTreadWidth['value_en'];
}
],
[
'attribute' => 'productAspectRatio.value_en',
'label' => Yii::t('app' , 'Aspect Ratio'),
'content' => function($model){
return $model->productAspectRatio['value_en'];
}
],
]
]);
?>
现在你可以对你喜欢的属性进行排序
我的问题要高一级:我想同时对 2 或 3 个属性进行排序 ASC 或 DESC
我希望3年后也有人回答我:D
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.