laravel second join return query as null - php

I have this query
$products = DB::table('product_attributes')
->where('product_attributes.attribute_id', '=', $attri->id)
->joinoin('products', 'products.id', '=',
->get();
and it returns
Collection {#2788 ▼
#items: array:2 [▼
0 => {#2785 ▶}
1 => {#2786 ▶}
]
}
but then I don't have access to my products cover image, so I changed my query to:
$products = DB::table('product_attributes')
->where('product_attributes.attribute_id', '=', $attri->id)
->join('products', 'products.id', '=', 'product_attributes.product_id')
->join('covers', 'covers.imageable_id', '=', 'products.id')
->get();
and it returns:
Collection {#2805 ▼
#items: []
}
empty!
Again I changed my query to:
$products = DB::table('product_attributes')
->where('product_attributes.attribute_id', '=', $attri->id)
->leftJoin('products', 'products.id', '=', 'product_attributes.product_id')
->leftJoin('covers', 'covers.imageable_id', '=', 'products.id')
->get();
and it returns:
Collection {#2807 ▼
#items: array:2 [▼
0 => {#2804 ▶}
1 => {#2805 ▶}
]
}
yet without having access to my covers (same as my first query).
question
How can I have access to my products with all other models relations?
More...
here is some of other relations to my product model
public function covers()
{
return $this->hasMany(Cover::class, 'imageable_id');
}
public function photos()
{
return $this->hasMany(Photo::class, 'imageable_id');
}
public function options(){
return $this->belongsToMany(Option::class, 'product_options', 'product_id', 'option_id');
}
public function attributes(){
return $this->belongsToMany(Attribute::class, 'product_attributes', 'product_id', 'attribute_id');
}
public function categories(){
return $this->belongsToMany(Category::class, 'product_categories', 'product_id', 'category_id');
}

If you have the relationships set-up you could do it in the following way:
$products = Product::with(['covers','attributes'])->whereHas('attributes', function ($query) use ($attri) {
$query->where('product_attributes.attribute_id', $attri->id);
})->get();
This way you get all your products which have an attribute with the given identifier and along with those products you will also retrieve the covers and attributes.
To access a cover or attribute in the first product for example you could do $products->first()->covers

Init only main object
$product = Product::findOrFail($id);
Use relations as object. Not use query-builder.
$product->covers();
$product->photos();

Related

laravel join select max of joined column

I have 3 table products, details and
detail_colors
I want select max "stock" from "detail_colors" and
max "price" from "details"
$products = Product::
join('details', function (JoinClause $join) {
$join->on('products.id', '=', 'details.product_id');
})
->join('detail_colors', function (JoinClause $join) {
$join->on('products.id', '=', 'detail_colors.product_id');
})
->select('products.*', DB::raw('max(details.price) as price'), DB::raw('max(detail_colors.stock) as stock'))
and its not working.
I use laravel 8.*
Can't you use aggregate functions on relationships?
$products = Product::query()
->withMax('details', 'price')
->withMax('detail_colors', 'stock')
Or you can define the relationship as such:
public function details()
{
return $this->hasOne(Details::class)->ofMany('price', 'max');
}
public function details()
{
return $this->hasOne(DetailColors::class)->ofMany('stock', 'max');
}

How to return data from 2 tables with foreign keys in laravel

I am trying to return a view with 2 tables, orders and order_menu. What I want to do is to display what orders the customer ordered based on order_id to my view.
Here is the database table for orders and this is database table for order_menu.
I've tried using join table in my controller but it won't work. Here is my controller:
public function show(Order $order)
{
$data = DB::table('order_menu')
->join('menus', 'menus.id', '=', 'order_menu.menu_id')
->join('orders', 'orders.id', '=', 'order_menu.order_id')
->select('orders.*', 'menus.name', 'order_menu.quantity')
->get();
return view('admin.order.detail')->with([
'order' => $order,
'data' => $data,
]);
}
Is there any solutions to solve this?
You just need to add a filter for order id in your query, I assume $order is the instance of model and has order data
$data = DB::table('order_menu')
->join('menus', 'menus.id', '=', 'order_menu.menu_id')
->join('orders', 'orders.id', '=', 'order_menu.order_id')
->select('orders.*', 'menus.name', 'order_menu.quantity')
->where('orders.id', $order->id)
->get();
Or if you already have relations in place in your model then using eloquent you can query the data as
class Order extends Model
{
public function menus()
{
return $this->belongsToMany(Menu::class, 'order_menu ', 'order_id', 'menu_id')->withPivot('quantity');
}
}
class Menu extends Model
{
public function orders()
{
return $this->belongsToMany(Order::class, 'order_menu ', 'menu_id','order_id');
}
}
$data = Order::with('menus')->find($order->id);
public function show(Order $order)
{
$data = DB::table('orders*')
->join('order_menu*', 'order_menu.id', '=', 'orders.id')
->groupBy('orders.id')
->get();
return view('admin.order.detail')->with([
'data' => $data,
]);
}

My instance doesn't fetch me the table that I want

So I am trying to attach an object full of information from the MYSQL DB, but the outcome isn't what I am expecting.
Controller -
public function index()
{
$location = Location::orderBy('created_at', 'desc');
return view('location')->with('locations', $location);
}
Model -
class Location extends Model
{
// Primary Key
public $primaryKey = 'id';
// Timestamps
public $timestamps = true;
}
Result -
Builder {#486 ▼
#query: Builder {#485 ▶}
#model: Location {#484 ▶}
#eagerLoad: []
#localMacros: []
#onDelete: null
#passthru: array:12 [▶]
#scopes: []
#removedScopes: []
}
Change this
$location = Location::orderBy('created_at', 'desc');
To
$location = Location::orderBy('created_at', 'desc')->get();
When using $location = Location::orderBy('created_at', 'desc'); it is a instance of Illuminate\Database\Query\Builder.
For get all records you must use
$locations = Location::orderBy('created_at', 'desc')->get();
It is return instance of \Illuminate\Database\Eloquent\Collection
For get Limited records you must use
$limit = 20; // or custom
$limitedLocations = Location::orderBy('created_at', 'desc')->limit($limit)->get();
For get single data use
$location = Location::orderBy('created_at', 'desc')->first();
It is return null or instance of model Location

hasMany Laravel Not working

$user = User::where('id', $id)->with(['experiences_user'])->first();
dd($user->experiences_user());
When i execute dd it's not showing the values of relationship have.
relations: array:1 [▼
"experiences_user" => Collection {#196 ▼
#items: []
}
User Model Relationships:
public function experiences_user(){
return $this->hasMany('App\experiences', 'User_id');
}
Experiences Model Relationships:
public function employee(){
return $this->belongsTo('App\User','User_id', 'id');
}
Try lazy loading:
$user = User::where('id', $id)->first()->load('experiences_user');

Removing item from collection change its type - Laravel

I'm using Laravel 5.4. This code retrieves users belonging to a company and return them to the client side.
The following query is used to get the user of the company
$users = User::where('company_id', '=', $idCompany)
->with([
'roles' => function($q) {
$q->whereBetween('level', [50, 999]);
}
])->get();
Situation A
return $users;
$users is an array of objects [{user1}, {user2}]
Situation B
foreach($users as $key=> $user) {
if(count($user->roles) == 0){$users->forget($key);}
}
return $users;
I remove some item from the collection and the
$users is an object of objects {{user1}, {user2}}
Removing an item from the collection seems to change the type of the variable $users
How could I remove some item from the collection while maintaining
the array of object?
EDIT
Here is the correct query
$users = User::whereHas('roles', function ($query) {
$query->whereBetween('level', [50, 999]);
})
->with('roles')
->where('company_id', '=', $idCompany)
->get();
return $users;
After manipulating the collection, you need to add ->all() to get the remaining collection;
return $users->all();
You could also do it this way
$filtered = $users->reject(function ($value, $key) {
return count($user->roles) == 0;
});
return $filtered->all();
As proposed by Alex in the comments, you could use whereHas() instead of with() to get directly all the users having a role between 50 and 999
$users = User::whereHas('roles', function ($query) {
$query->whereBetween('level', [50, 999]);
})
->where('company_id', '=', $idCompany)
->get();

Categories