2016-05-25 31 views
0

我有產品型號,我有類別型號。我也有一個名爲category_product的數據透視表。我試圖在我的CategoryController上設置一個orderByLaravel - 如何使用雄辯在FK上設置orderBy?

Product.php

public function category() 
{ 
    return $this->belongsToMany(Category::class, 'category_product', 'category_id', 'product_id'); 
} 

Category.php

public function products() 
{ 
    return $this->hasMany(Product::class); 
} 

CategoryController.php

public function index() 
{ 
    // works 
    $categories = Category::where('parent_category_id', 0)->orderBy('name', 'asc')->get(); 

    // Unknown column 'category_product.sort_key' 
    $categories = ProductCategory::where('parent_category_id', 0)->orderBy('category_product.sort_key', 'asc')->orderBy('name', 'asc')->get(); 


    return view('category.index', compact('categories')); 
} 

我數據透視表如下所示:

product_id 
category_id 
sort_order 

我遵循建議的表命名約定。我甚至傳遞了透視表名稱以保證安全。 - 我不知道如何在我的查詢中包含數據透視表。

我也相信這是我無法正確訪問列的原因。 例如:

Product.php

$this->categories->myColumn // Undefined property 

我的遷移是這樣的:

... 
$table->foreign('product_id')->references('id')->on('products'); 
$table->foreign('category_id')->references('id')->on('categories'); 

謝謝你的任何建議!

編輯

我已經更新了邏輯的建議,我仍然不認爲我已經得到了參加完全正確呢。

Category.php

public function products() 
{ 
    return $this->belongsToMany(Product::class, 'category_product', 'category_id', 'product_id') 
     ->withPivot('sort_key'); 
} 

Product.php

public function categories() 
{ 
    return $this->belongsToMany(Category::class, 'category_product', 'category_id', 'product_id') 
     ->withPivot('sort_key'); 
} 

CategoryController.php

public function index() 
{ 
    $categories = Category::where('parent_category_id', 0) 
     ->orderBy('sort_order', 'asc') 
     ->orderBy('name', 'asc') 
     ->get(); 

    return view('category.index', compact('categories')); 
} 

Column not found: 1054 Unknown column 'sort_order' in 'order clause 

如果我參加了->orderBy('sort_order', 'asc')一切都很好。我也試過->orderBy('category_product.sort_order', 'asc'),沒有運氣。

回答

0

首先,根據the documentation,多對多關係的逆並非hasMany,而是belongsToMany。第3行的類別。PHP文件應該閱讀:

return $this->belongsToMany(Product::class); 

如果你想,當你檢索任何一個類別或產品型號使用sort_order列在數據透視表,您需要在兩者的產品和類別模型withPivot()方法定義像這樣:

Product.php

public function category() 
{ 
    return $this->belongsToMany(Category::class, 'category_product', 'category_id', 'product_id') 
    ->withPivot('sort_order'); 
} 

Category.php

public function products() 
{ 
    return $this->belongsToMany(Category::class, 'category_product', 'category_id', 'product_id') 
    ->withPivot('sort_order'); 
} 

一旦做到這一點,說你想獲得的所有產品,爲id爲2.你可以做這樣的事情在你的CategoryController類別:

CategoryController.php

public function index() 
{ 
    // Get all products for category with an id of 2 
    $Products = Category::find(2)->products; 

    // Assign the sort_table attribute to each Product model. Can be done 
    // in the model definition by setting an accessor attribute. Setting 
    // it here for expediency. 

    foreach($Products as $Product) $Product->sort_order = $Product->pivot->sort_order; 

    // Sort products in descending order using the sort_order column from 
    // the pivot table. 
    $SortedProducts = $Products->sortByDesc('sort_order'); 
} 

對產品進行分類的最後一行是Collection Method。收集方法幾乎總是比模型中的硬編碼排序順序更強大,因爲你可以使許多方法鏈流暢,例如:

$SortedProducts = $Products->where('status', 'available') 
          ->sortBy('product_name'); 

你也讓你的代碼有很多清潔赫克和潛在的避免稍後在應用程序中再次創建另一個數據庫查詢,只是爲了以不同的方式對結果進行排序,從而使所有內容都變得更快一些。

編輯

當你調用Category::門面,什麼你告訴Laravel做的是,就您在分類模型所定義的表的查詢。默認情況下,它與模型名稱相同。考慮到這一點,除非categories表上有sort_order,否則Laravel會抱怨找不到sort_order列。

如果你做這樣的事情,但是:

public function index() 
{ 
    $Products = Category::find(2)->products; 

    $products = $Products->toArray(); 

    var_dump($products); 
} 

...你會發現一個sort_order子鍵沿pivot關鍵。

簡而言之,Laravel只會在實際使用數據透視表時纔會附加數據透視表的列,如上例所示。如果你想在不調用您在產品和類別模型中定義的許多一對多的關係,以獲得sort_order列,一個簡單連接就可以了:

public function index() 
{ 
    $categories = Category::where('parent_category_id', 0) 
     ->join('category_product', 'categories.id', '=', category_product.category_id) 
     ->orderBy('category_product.sort_order', 'asc') 
     ->orderBy('name', 'asc') 
     ->get(); 

    return view('category.index', compact('categories')); 
} 
+0

非常感謝你的詳細解答亞歷克斯!我仍然遇到一些麻煩 - 我已經在上面編輯了我的問題。 – Damon