I have three tables.
Categories
Products
Brands
I have a relation on my categories table to the products like so:
public function products()
{
return $this->belongsToMany('App\Product','product_sub_categories','subcategory_id','product_id');
}
I have a relation on my Products table to the brands like so:
public function manuf()
{
return $this->belongsTo('App\Brand','brand');
}
I'm querying the categories table to return products of that category by a certain brand.
For example.
I wan to see all products in Cars category with the brand Fiat.
I've tried the following but I feel Im missing something..
$search = 'fiat';
$products = $category->products()->where(function($query) use ($search){
$query->brand->name = $search;
})->get();
to return products of that category by a certain brand
I assume that you know brand ID and category ID and that products and categories have many to many relationship (since you're using belongsToMany) and product belongs to brand:
Product::where('brand_id', $brandId)
->whereHas('categories', function($q) use(categoryId) {
$q->where('id', $categoryId);
})
->get();
Related
I'm making an attempt to write Eloquent join query but i didn't get the result i wanted.
i have 2 table
products which contains all information about products
category_product contains product_id and category_id
i just want to select all information about products which their category_id is equal to 2
After you have belongsToMany relation between categories and products.
Product::whereHas('categories', function($query){
$query->where('id',2);
})->with('categories')->get();
I can offer you a solution like this
class Product extends Model
{
public function category()
{
return $this->morphToMany(Category::class, 'category_product table');
}
}
class Category extends Model
{
public function product()
{
return $this->morphedByMany(Product::class, 'category_product table');
}
}
in Controller
$products = DB::table('products')
->join('category_product', 'products.id', '=', 'category_product.products_id')
->select('products.*')
->where('category_product.category_id','=',2)
->get();
I am building an ecommerce website using Laravel 5.8 and have the following problem. I want to retrieve all products from a category and its child categories, but to be able to perform filtering queries afterwards in my code. For example price limits and quantitative availability on the products.
The store has categories, which have child categories in the same table.
Categories table (Simplified) - id|name|parent_id - Where if parent_id != 0, then the category is considered a child to a main category.
The products can be in more than one category and therefore I'm using a many to many relationship.
Products table (Simplified) - id|name...
Product categories table - id|product_id|category_id
My Products model look like this:
public function categories()
{
return $this->belongsToMany(
'App\CatalogCategory',
'catalog_product_categories',
'product_id',
'category_id'
);
}
And my Categories model:
public function allProducts()
{
return $this->belongsToMany(
'App\CatalogProduct',
'catalog_product_categories',
'category_id',
'product_id'
)
->where('is_active', 1)
->whereDate('active_from', '<=', Carbon::now('Europe/Sofia'))
->where(function ($query)
{
$query->whereDate('active_to', '>=', Carbon::now('Europe/Sofia'))
->orWhereNull('active_to');
})
->wherePivotIn('category_id', $this->allChildrenIds());;
}
Currently doing this, returns an empty collection:
$category = CatalogCategory::find(3);
dd($category->allProducts);
Okay I guess the problem is ->wherePivotIn('category_id', $this->allChildrenIds()).
You are trying to get products for a category - corresponding records can be identified by a row in pivot table which has this category's id with various other product_id.
But the wherePivotIn doesn't contain current category's id in $this->allChildrenIds() so no records are returned.
Define the relation without the wherePivotIn
public function allProducts()
{
return $this->belongsToMany(
'App\CatalogProduct',
'catalog_product_categories',
'category_id',
'product_id'
)
->where('is_active', 1)
->whereDate('active_from', '<=', Carbon::now('Europe/Sofia'))
->where(function ($query)
{
$query->whereDate('active_to', '>=', Carbon::now('Europe/Sofia'))
->orWhereNull('active_to');
});
}
Then to get all products for current category and all it's subcategories
$category = Category::with(['products', 'subcategories.products'])->get();
With this query the products associated with subcategories will be nested under each subcategory respectively.
I am new to laravel & want to implement eloquent relationship.
Let me explain.
Consider I have 2 tables
products
product_id
product_name
brand_id
price
brands
id
brand_name
Each product will have one brand Id.But in Brands table, there is no product id. One brand_id can be in multiple product rows, and one product has one brand_id only. I want to select some col from products table plus brand_name with respect to brand_id of products table using Model.SO in Product model I wrote:
public function brands()
{
return $this->hasOne('App\Brand','product_id');
}
and in Brand model I write:
public function products()
{
return $this->belongsTo('App\Product','brand_id');
}
Now I want the result:
product_name
price
brand_name
How can I fetch those data in controller using eloquent relation? Also, the way I wrote Model relationship, Is it ok??
Your Product Model relation will be below
public function brand(){
return $this->belongsTo('App\Brand','brand_id');
}
public function product(){
return $this->belongsTo('App\Product','product_id');
}
Now in controller you can add query as below.
$products = Product::with('brand','product')->get();
echo '<pre>'
print_r($products->toArray());
exit;
It looks to me like you want a one-to-many relationship, so one brand can have many products and many products belong to one brand.
Product model:
public function brand()
{
return $this->belongsTo('App\Brand');
}
Brand model:
public function products()
{
return $this->hasMany('App\Product');
}
Then you would be able to get the brand information like this:
The full brand model:
Product::first()->brand
The brand name:
Product::first()->brand->brand_name
From the docs:
A one-to-many relationship is used to define relationships where a
single model owns any amount of other models. For example, a blog post
may have an infinite number of comments.
P.S.:
Your table column names do not make much sense to me, why do you have product_id on products but then on brands it is just called id? Why do you have product_name but then just price? why is it not just name or product_price, so your at least consistent?
I have model many-to-many (including pivot table). I need to pull out only the products that belongs to a certain category. I'm trying this but it gives me all the products:
$products = User::whereHas('category', function ($query) {
$query->where('id','1');
})->get();
1 in where is just for testing because when I put $id that was defined outside query it doesn't recognize it.
Try this.
$products= User::whereHas('category', function ($query) use ($id) {
$query->where('id', $id);
})->get();
Maybe the fetchProducts method here will shed some light: Getting product brands, their categories and associated products
I will describe this situation with more details:
I have a list of products where every product belongs to a certain category and to a certain brand. Some of the products can get reviewed by users.
On /reviews/ page in my Laravel application, I have a list of reviews and select boxes for category and brand along with search button of course.
If user doesn't choose category or brand, all reviews get displayed, paginated, and that's good.
The problem arises when user chooses either category or brand or both and tries to get all the reviews filtered that way.
Reviews table fields: ID, user_id(foreign key users.ID), product_id(foreign key products.ID), text
Products table fields: ID, category_id(foreign key categories.ID), brand_id(foreign key brands.ID), name
Categories table fields: ID, name
Brands table fields: ID, name
Users table fields: ID, username
When I'm listing reviews, I'm simply using:
$reviews = Review::orderBy('id', 'DESC')->paginate(5);
If I would like to filter reviews by user_id, that would be easy as the reviews table contains user_id column,
but, how to filter them by product category and/or product brand?
Here are Review, Product and Category models:
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Review extends Model {
protected $fillable = [];
public function product() {
return $this->belongsTo('App\Product');
}
public function user() {
return $this->belongsTo('App\User');
}
}
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model {
protected $fillable = [];
public function user() {
return $this->belongsTo('App\User');
}
public function reviews() {
return $this->hasMany('App\Review');
}
public function category() {
return $this->belongsTo('App\Category');
}
}
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model {
protected $fillable = [];
public function products() {
return $this->hasMany('App\Product');
}
}
If I use joins, then $review->user->id, $review->user->username, $review->id are not correct, I'm getting reviews.product_id as $review->id, and products.user_id as $review->user->id in blade template.
I was trying this join variant:
$reviews_query = Review::orderBy('reviews.id', 'DESC')
->Join('products', 'reviews.product_id', '=', 'products.id')
->Join('categories', 'products.category_id', '=', 'categories.id')
->Join('brands', 'products.brand_id', '=', 'brands.id')
->Join('users', 'reviews.user_id', '=', 'users.id')
->where('reviews.active', '=', 1)
->GroupBy('reviews.id')->paginate(5);
And this for filtering by category_id:
if (Input::has('category_id')){
$category_id = Input::get('category_id');
$reviews_query->where('categories.id', $category_id);
}
I'm not sure how to correctly address ambiguous ids such us product_id, review_id, user_id in blade template ($review->id, $review->user->id, all are messed up mutually)
Add hasManyThrough relationship in your category model
public function reviews() {
return $this->hasManyThrough('App\Review', 'App\Product');
}
now you can have all reviews by a category like this
$category->reviews();
you can add other query clauses to it like
$category->reviews()->orderBy('id', 'DESC')->paginate(5);
Try this,
$reviews = DB::table('review')
->join('product', 'product.id', '=', 'review.product_id')
->Join('category', 'product.category_id', '=', 'category.id')
->orderBy('id', 'DESC')->paginate(5);
for more you can visit-
Laravel join with 3 Tables
This may work for you.....
filter all reviews by a specific CategoryID then simply use ->
$categoryID = 1;
Categories::with(['products' => function($product){
$product->with('reviews');
}])->where('id', '=', $categoryID)->get();
also filter all reviews by a specific BrandID then
$brandID = 1;
Brands::with(['products' => function($product){
$product->with('reviews');
}])->where('id', '=', $brandID)->get();