我有三個表。products, product_inventories 和 product_inventory_details。每個模型的ORM如下所示,
產品模型
class Product extends Model{
...
/**。
*可大規模分配的屬性。
*
* @var陣列
*/
protected $fillable = [
...,
'title',
'selected_inventory_id'。
...
];
/**。
*獲得屬于這個模型的庫存。
*/
public function inventory() {
return $this-> hasMany('AppModelsProductInventory')。
}
/**。
*獲取擁有此模型的選定的product_inventory_detail。
*/
public function selected(){
return $this-> hasOne('AppModelsProductInventoryDetail'/span>, 'id'/span>, 'selected_inventory_id'/span>)。
}
...
}
ProductInventory模型
class ProductInventory extends Model{
...
/**。
*可大規模分配的屬性。
*
*@var陣列
*/
protected $fillable = [
'product_id',
...
];
/**。
*獲得屬于這個模型的inventory_details。
*/
public function items(){
return $this->hasMany('AppModelsProductInventoryDetail' )。)
}
...
}
ProductInventoryDetail模型
class ProductInventoryDetail ProductInventoryDetail extends Model{
...
/**。
*可大規模分配的屬性。
*
*@var陣列
*/
protected $fillable = [
'product_inventory_id',
'price',
...
];
}
我正在通過用戶輸入的Sort by下拉選單和Show per page下拉選單對結果進行排序和限制。當按Alphabetical: High to Low選項排序時,我正在運行query builder方法來排列結果:
$products = $products-> orderBy($sort['column'], $sort['order'])-> paginate($limit)。
現在按Price排序,我不能運行查詢生成器方法orderBy(),因為我沒有使用連接和通過關系屬性獲取資料。相反,我使用Laravel的collection方法來整理它:
$products = $products-> paginate($limit) 。
$products = $products-> sortBy(function($prod, $key) {
return $prod-> selected->price;
});
如果我不使用分頁方法,上面的塊可以正常作業。但是,我也需要使用分頁,因為用戶也可以限制每頁的結果。我還使用了一個Paginator物件的方法,將一些引數附加到每個頁面的URL上:
$products->appends($paramsArr) 。
由于運行sortBy()方法回傳一個集合而不是Paginator物件,它給了我undefined method例外。
我的問題
在我目前的情況下,我怎樣才能按價格對結果集進行排序,而不需要實作連接?有什么方法可以實作嗎?
uj5u.com熱心網友回復:
我將使用Spatie的QueryBuilder包。它將使你的生活更容易創建可排序和可過濾的網格表。你可以這樣使用該包:
$query = Product::with(['banking', 'selected']) 。
$products = SpatieQueryBuilderQueryBuilder::for($query)
->allowedFilters([
'name' => 'name', //name column in the products DB table.
'selected.price' => 'product_inventory_details.column_price', // products_inventory_details DB表中的價格列。
])
->defaultSort('name')
-> allowedSorts([
'name',
SpatieQueryBuilderAllowedSort::custom('selected.price', new SortSelectedPrice()
])
->分頁(20)
->appends(request()->query())。
外部自定義排序類看起來像這樣:
class SortSelectedPrice implements SpatieQueryBuilderSortsSort
{
public function __invoke(Builder $query, bool $descending, string $property)
{
$direction = $descending ? 'DESC'/span> : 'ASC'/span>。
$query-> leftJoin('product_inventory_details', 'products. id', '=', 'product_inventory_details.product_id')。)
$query->orderBy('product_inventory_details.column_price', direction);
}
確保你的URL包含像這樣的查詢字串,以便將名稱從A到Z排序,將價格從1xxxxxxxx到0排序:
domain.com/products?sort=name,-selected.price
我使用composer安裝了Spatie包。不要忘記這樣做。
uj5u.com熱心網友回復:
我找到了一種無需實作連接的處理方法。我添加了一個新的變數,并將Paginator物件的items()方法結果集存盤在其中。
$products = $products->paginate($limit)。
$productItems = $products->items(); // return the items array from paginator.
并且對該特定變數進行排序,而不是對整個paginator物件進行排序。這樣,我的鏈接和URL在$products變數中未被觸及和修改,而產品的資料在一個單獨的變數中。
if($sort[' column'] == 'price'){
if($sort['order'] == 'desc'){
$productItems = $products-> sortByDesc(function($prod, $key) {
return $prod-> selected->price;
});
} else{
$productItems = $products-> sortBy(function($prod, $key) {
return $prod-> selected->price;
});
}
}
我也不得不將我的渲染變數從$products改為$productItems,并從舊的$products變數中訪問分頁鏈接。
@forelse ($productItems as $product)
@include('site.components.product-grid')
@empty
<div class="col text-center"> ...</div>
@endforelse[/span
...
{{$products->links() }}。
我把它貼在這里,讓社區受益/討論/批評,如果有更好的方法。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/334007.html
標籤:
上一篇:SQL-檢查一組類似記錄中的任何記錄是否與一個ID匹配
下一篇:從不同的引數回傳計數
