I have collections which contains custom products I need to paginate those collections products but I receive error.
data
With this query I can get my collection and it's products but I'm not able to paginate products.
$collection = Collection::where('slug', $slug)->where('status',
'active')->with('products')->first();
With this query I receive error
$collection = Product::with('collections')->whereHas('collections',
function($query) use($slug) { $query->where('slug',
$slug)->where('status', 'active')->first(); });
Error
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'shopping.product_id' doesn't exist (SQL: select * from `collection_products` inner join `product_id` on `collection_products`.`id` = `product_id`.`collection_product_id` where `products`.`id` = `product_id`.`product_id` and `slug` = test and `status` = active limit 1)
Code
Product model
public function collections()
{
return $this->belongsToMany(CollectionProduct::class, 'product_id');
}
Collection model
public function collection(){
return $this->belongsToMany(CollectionProduct::class);
}
public function products(){
return $this->belongsToMany(Product::class, 'collection_products', 'collection_id', 'product_id');
}
CollectionProduct model
public function collection()
{
return $this->belongsTo(Collection::class, 'collection_id','id');
}
Controller default query
public function single($slug){
$collection = Collection::where('slug', $slug)->where('status', 'active')->with('products')->first();
return view('front.collections.single', compact('collection'));
}
Question
How can I get my collection products with pagination ability?
Couple things:
You are trying to call the first() method inside of a relationship query in this line:
$collection = Product::with('collections')->whereHas('collections', function($query) use($slug) { $query->where('slug', $slug)->where('status', 'active')->first(); });
The methods first() and get() are used to execute the query, so you should keep them at the end of the chain of eloquent methods:
$collection = Product::with('collections')
->whereHas('collections', function($query) use($slug) {
$query->where('slug', $slug)->where('status', 'active');
})
->get();
https://laravel.com/docs/5.7/eloquent#retrieving-models
However, if you want to paginate the list of products, then what you really want is the paginate() method:
$collection = Product::with('collections')
->whereHas('collections', function($query) use($slug) {
$query->where('slug', $slug)->where('status', 'active');
})
->paginate(20); // will return 20 products per page
https://laravel.com/docs/5.7/pagination
Also, the collections() method on your Product model has product_id listed as the join table, and is joining to the CollectionProduct model instead of the Collection model.
Try this instead for your Product model:
public function collections()
{
return $this->belongsToMany(Collection::class, 'collection_products', 'product_id', 'collection_id');
}
i use following code and working very well
the first step get product
$product = Product()->find($product_id);
than i get collections and pagination
$collections = Product::find($product_id)->collections->paginate(20);
for example i used above code in this site.
Related
I've spent two days trying to solve this but I can't figure how.
I have five tables
Product
Category
Category_Product
Order
Order_Product
From the view,clicking on a category button I have to fetch all his ordered products with the relative category.
I have the current models:
Product Model
class Product extends Model
{
public function categories() {
return $this->belongsToMany('App\Category');
}
public function orders() {
return $this->belongsTo('App\Order');
}
}
Category Model
public function products() {
return $this->belongsToMany('App\Product');
}
Order Model
public function products() {
return $this->belongsToMany('App\Product');
}
Now the problem is that I can't figure how to fetch the data from the current tables.When I press a button I'm able to fetch the category from the Product Table,but I want to fetch from the Ordered_Products. I really can't figure how.
With this I'm able to fetch all the categories from Product
if (request()->category) {
$products = Product::with('categories')->whereHas('categories', function ($query) {
$query->where('slug', request()->category);
})->get();
}
With this instead,I'm able to fetch the ordered products.
$products = DB::table('order_product')
->join('products', 'order_product.product_id','=', 'products.id')
->where('order_product.user_id','=',$user_id)
->get();
For the latter, there's a better way to do it, that's for sure. I'm sorry if it's a dumb question but I'm rather new with this framework. I am using Laravel 7.2.
Basically Eloquent Model doesn't encourage joining tables to retrieve data. It should be joined only for filtering results (So you need to drop field of other table using ->select('original_table.*'))
In this case, you should simply retrieve categories at first. Then retrieve related data using relation property accessing.
e.g.
$categories = Category::query()
->with('products')
->where('slug', request('category'))
->get();
$products = $categories->flatMap->products;
$pivots = $products->map->pivot;
Solved using whereHas two times:
$products = Product::with('categories')->whereHas('categories',function($query){
$query->where('slug',request()->category);
})->whereHas('orders',function($query){
$query->where('orders.user_id',Auth::id());
})->get();
I have categories and products tables. They are related with Many to Many relationships.. I want to get products by categories and selected price range but whereHas clause dosen't work
$products = Product::whereHas('categories',function ($query) use ($slug){
$query->where('category_slug',$slug);
})->whereBetween('price',[100,200])->get();
Category Model;
public function products(){
return $this->belongsToMany('App\Product','category_product','category_id','product_id');
}
Product Model;
public function categories() {
return $this->belongsToMany('App\Category','category_product','product_id','category_id');
}
So, what is my mistake in here ?
I created a relationship between the "Review, Games and Info" tables, unfortunately, though, the main table is Games, and he orders me all for Games, While I would like to order the ID of "review" table.
Models: Review
public function games()
{
return $this->hasMany('App\Models\Giochi', 'id_gioco', 'id');
}
Models: Giochi
public function review()
{
return $this->belongsTo('App\Models\Review', 'id', 'id_gioco');
}
public function infogiochi()
{
return $this->belongsTo('App\Models\InfoGiochi', 'id', 'id_gioco');
}
Models: InfoGiochi
public function games()
{
return $this->hasMany('App\Models\Giochi', 'id', 'id_gioco');
}
Controller:
$review = Giochi::with('Review','InfoGiochi')->orderBy('id','DESC')->get();
Here is a screenshot of my json:
How do I order content for review table IDs?
You have 2 options. You use a join and order in the sql statement or you order it after retrieving the results in the collection.
Using Join
Giochi::select('giocos.*')
->with('Review','InfoGiochi')
->leftJoin('reviews', 'reviews.id', '=', 'giocos.id_gioco')
->orderBy('reviews.id','DESC')
->get();
Sorting Collection
Giochi::with('Review','InfoGiochi')
->get()
->sortByDesc(function($giochi) {
return $giochi->review->id;
});
This would be the shortest version to sort on the collection:
Giochi::with('review')
->get()
->sortByDesc('review.id');
You can modify your relationship query when you fire it:
Giochi::with([
'Review' => function ($query) { return $query->orderBy('id','DESC'); },
'InfoGiochi'
])->orderBy('id','DESC');
You can try with a raw query or you can use ->orderBy() directly on review function.
I have two tables, say Products and Biddings where one product can be bid by many users. Naturally I have two models:
class Product extends Model
{
public function biddings()
{
return $this->hasMany('App\Bidding');
}
}
class Bidding extends Model
{
public function product()
{
return $this->belongsTo('App\Product');
}
}
So, say I want to get all products along with the highest priced bidding I did something like this.
$productBidding = DB::table('biddings')
->select('*', DB::raw('max(price) as price'))
->join('products', 'products.id', '=', 'biddings.product_id')
->groupBy('product_id')
->get();
That works well BUT I kinda want to do it Eloquent way. So how do I convert Query Builder way to Eloquent? I am currently on this but do not know how to put the "max" condition in.
$productBidding = Products::with('biddings')
->get();
$productbinding=Bidding:with('product')
->get();
foreach($productbinding as $productbind)
{
echo $productbind->product->name; // example
}
I would extract the highest bid to a separate function on the Product model, like so:
public function highestBid() {
return $this->biddings()->max('price');
}
Then fetch the products and get the highest bid:
$products = Product::get();
foreach ($products AS $product) {
echo $product->highestBid();
}
My Model Items is related to Rooms, which is related to Buildings, which is related to Locations.
Short: Items belongsTo Rooms belongsTo Buildings belongsTo Locations
At the index function of the ItemController I want to show a table of Items. I use Laravel Datatables. It works for 'simple' tables, but I ran into the problem of sorting/searching custom/appended fields, because they are not in the table of course.
Basically I want to join the Room, Building and Location Name for each Item in the displaying table.
This is my Items Model:
protected $appends = [
'building_title',
'location_title',
'room_title',
];
public function getLocationTitleAttribute() {
return $this->room->building->location->title;
}
public function getBuildingTitleAttribute() {
return $this->room->building->title;
}
public function getRoomTitleAttribute() {
return $this->room->title;
}
This is my Controller:
public function anyData()
{
return Datatables::of(Item::query())->make(true);
}
What is the best approach to enable sorting/filtering for appended fields?
Thank you for reading.
This is my solution (no appended fields were used):
public function anyData()
{
$items = Item::join('rooms', 'items.room_id', '=', 'rooms.id')
->join('buildings', 'rooms.building_id', '=', 'buildings.id')
->join('locations', 'buildings.location_id', '=', 'locations.id')
->select([
'items.id',
'items.title',
'items.label_number',
'items.fibu_number',
'rooms.title as room_title',
'buildings.title as building_title',
'locations.title as location_title'
]);
return Datatables::of($items)->make(true);
}