laravel 8 Eloquent query builder - php

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();

Related

sort by relation laravel

I need sort products by certain attribute id and his value. I have model Product with relation:
public function attribute()
{
return $this->hasMany('App\Models\ProductAttribute');
}
ProductAttribute model have:
public function attribute()
{
return $this->belongsTo('App\Models\AttributeValue', 'attribute_value_id');
}
I need sort products where attribute_id = 5 and with all values of this attribute. I try do this:
$products = Product::active()->where(function($query) {
$query->whereHas('attribute.attribute', function($q) {
$q->where('attribute_id', 5)->orderBy('value', 'desc');
});
})->get();
But this is not working.
Structure table of model Product Attribute:
id
attribute_value_id
product_id
Structure table of model AttributeValue:
id
attribute_id
value
In value can be numeric values.
Please help me resolve this problem.
You should use joins:
$products = Product::active()
->select('products.*')
->leftJoin('product_attribute', 'product_attribute.product_id', '=', 'products.id')
->leftJoin('attribute_values', function($query){
$query
->on('attribute_values.id', '=', 'product_attribute.attribute_value_id')
->where('attribute_id', '5');
})
->groupBy('products.id')
->orderByDesc('attribute_values.value');
Not sure about table names.

Querying Laravel Eloquent Relationship

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();

Laravel Eloquent: how to filter reviews of products by product category and/or product brand?

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();

Eloquent many to many relationship access table column value from pivot table

I have two models:
class Order extends Eloquent
{
public function User()
{
return $this->belongsTo('User');
}
public function Product()
{
return $this->belongsToMany('Product');
}
}
and the second one is:
class Product extends Eloquent
{
public function Order()
{
return $this->belongsToMany('Order');
}
}
My question is how can i access a value of second table column using pivot table:
product table:
id
title
image
order table:
id
status
pivot table(order_product):
id
product_id
order_id
I need to access title column of products from orders. for example if a user orders many products in one order I can fetch all product title and show theme.
I don't like use join , instead I like to use Laravel functionality itself.
I found the answer:
$orders = Order::orderBy('created_at', 'DESC')->paginate($page_number);
foreach($orders as $item){
foreach($item->product as $item){
{{$item->title}}<br>
}
}
I can access products from order.

Laravel Eloquent join several tables

I have 3 tables:
products
|id|name|about|
=categories=
|id|name|parent|
=products-categories=
|id|product_id|cat_id|
I need to take a product categories names. I have a sql query:
SELECT s.name FROM products AS p
LEFT JOIN `products-categories` AS cats ON p.id = cats.product_id
LEFT JOIN `categories` AS s ON cats.cat_id = s.id
WHERE product_id = 1;
And It works! But how I can do this with the help of Laravel Eloquent (Not Fluent!)
You can use Eloquent relationship and in this case, create two models, for both tables, i.e. product and Category:
class Category extends Eloquent {
protected $table = 'categories'; // optional
public function products()
{
return $this->belongsToMany('Product', 'products_categories', 'category_id', 'product_id');
}
}
class Product extends Eloquent {
protected $table = 'products'; // optional
public function categories()
{
return $this->belongsToMany('Category', 'products_categories', 'product_id', 'category_id');
}
}
Now you may use these relationship methods to get related data, for example:
$product = Product::with('categories')->find(1);
This will return the product with id 1 and all the related categories in a collection so you may use $product->categories->first()->name or you may do a loop on the categories like:
foreach($product->categories as $cat) {
echo $cat->name;
}
Also you may use join which doesn't require the relationship methods and you may use same approach to join the models that is used in Fluent (Check other answer). But either way, you need to store the category and product mappings in the products_categories table. Read more about many-to-many relationship on Laravel website.
Just use the leftJoin method. It works the same in Eloquent as in Query Builder.
$product = Product::leftJoin('product-categories', 'product-categories.product_id', '=', 'products.id')
->leftJoin('categories', 'categories.id', '=', 'product-categories.cat_id')
->where('product_id', 1)
->first(['categories.name']);

Categories