Eloquent GroupBy with hasManyThrough relationship - laravel

I have three models - Company, Driver that belongs to a company, and Order that belongs to a driver. I have stated the relationship between companies and booking like:
public function orders() {
return $this->hasManyThrough(Order::class, Driver::class);
}
But! If I want to get all orders grouped by companies how do I do that?

you can make Accessor in your order model to get company_id
public function getCompanyIdAttriubte(){
return $this->driver->company->id;
}
then to get orders group by company_id
$orders = Order::all();
$orders = $orders->groupBy('company_id');
you can view these links to understand what id did exactly
https://laravel.com/docs/5.7/collections#method-groupby
https://laravel.com/docs/5.7/eloquent-mutators#defining-an-accessor

You have two ways:
First:
$companies = Company::with(['orders', 'orders.user'])
->whereHas('orders')
->get();
foreach($companies as $company){
echo $company->id;
foreach($company->orders as $order){
echo $order->driver->id;
echo $order->id;
}
}
Second:
$orders = Orders::with(['driver', 'driver.company'])->get();
$orders = $orders->groupBy(function($order){
return $order->driver->company_id;
});
foreach($orders as $companyId => $group){
foreach($group as $order){
echo $order->id;
echo $oder->driver->id;
echo $order->driver->company->id;
}
}

Related

Laravel fetch intermediate table data with many to many relationship

I have 3 tables
user, specialities & results
results contain specialitie_id, user_id
I have create many-to-many relationship
Here's the relationship in user model
public function specialities()
{
return $this->belongsToMany(Speciality::class, 'results', 'user_id', 'specialitie_id')->withPivot('result', 'color');
}
I want to fetch data from the result table based on specialitie_id
If my url is
abc.com/result/5
I have attached table structure as well,
it should show me result related to specialitie_id 5
I tried this but it doesn't work
$result = User::with('specialities')->where('id', 5)->get();
Any help would be appreciated.
Your current query:
$result = User::with('specialities')->where('id', 5)->get();
Is saying, give me all results where the USER_ID = 5 WITH all the specialities related to it.
You are very close but did it backwards:
//Give me all results where the SPECIALITY_ID = 5
//WITH all the users related to it
$result = Speciality::with('users')->where('id', 5)->get();
Please note that the above is an array
Example of a Controller Function:
public function results($id){
$results = Speciality::with('users')->where('id', $id)->get();
return view('user_specialities', compact('results'));
}
Example view user_specialities:
#foreach($results as $result)
<p>Result: {{$result->result}}</p>
<p>Formulary: {{$result->formulary}}</p>
<p>Color: {{$result->color}}</p>
<p>User ID: {{$result->user->id}}</p>
<p>User Name: {{$result->user->name}}</p>
#endforeach
Speciality Model:
public function users()
{
return $this->belongsToMany(User::class, 'results', 'specialitie_id', 'user_id')->withPivot('result', 'color');
}
User Model:
public function specialities()
{
return $this->belongsToMany(Speciality::class, 'results', 'user_id', 'specialitie_id')->withPivot('result', 'color');
}

Laravel: sort query results based on field of nested relationship

I have two models with relations as defined below
Order
public function owner()
{
return $this->belongsTo(User::class, 'owner_id');
}
User
public function company(){
return $this->belongsTo(Company::class, 'company_id');
}
company table have 'title' field.
what I want is to get all the orders sorted/order by company title. I've tried different solution but nothing seems to work. Any help or hint would be appreciated.
Recent solution that I tried is
$query = OrderModel::whereHas('owner', function($q) use ($request){
// $q->orderBy('owner');
$q->whereHas('company',function ($q2) use ($request){
$q2->orderBy('title',$request->get('orderByDirection') ?? 'asc');
});
});
but I am not getting user and company relation in query results. also the result remains same for 'ASC' and 'DESC' order.
You could sort the query after adding join like:
return Order::join('users', 'users.id', '=', 'owner_id')
->join('companies', 'companies.id', '=', 'users.company_id')
->orderBy('companies.title')
->select('orders.*')
->get();
You can define new relations in User and Company models.
User
public function orders()
{
return $this->hasMany(Order::class);
}
Company
public function users()
{
return $this->hasMany(User::class);
}
Now you can fetch companies that are in asc order and with the use of relation, you can fetch users and orders. So the ORM like be,
$companies = Company::with('users.orders')->orderBy('title', 'ASC')->get();
So these are the company-wise orders. You can use this too.

Check if related model have entry in another related model

i have following models and there relation
Models
User
Product
Orders
OrderProduct
ProductReviews
Relations
User hasMany Orders
Orders hasMany OrderProdut
User hasMany ProductReview
Product hasMany ProductReview
ProductReview belongsTo User
Inside the product page all the reviews for that product is listed with the user details who made the review.
I want to check if review in list has made a purchase of the reviewed product.
So far i have done this with php loops and eager loading. Is there a better way to do this
$product = Product::with([
'reviews'=>function($q) {
$q->where('status', 1);
},
'reviews.user'
])->first();
if($product){
$product->load(['reviews.user.orders.orderProducts' => function($q) use($product){
$q->where('product_id',$product->id);
}]);
}
foreach ($product->reviews as $review){
$review->purchased_from_microless = false;
foreach ($review->user->orders as $order) {
if($order->orderProducts->count()){
$review->purchased_from_microless = true;
break;
}
}
}
It is possible to inline the query to check if reviewed product was purchased:
$product = Product::with([
'reviews' => function($q) {
$q->where('status', 1);
},
'reviews.user.orders'
])->first();
$reviews = $product
->reviews
->map(function ($value, $key) {
$wasPurchased = $review->user->orders->orderProduct()->where('product_id', $product->id)->count() > 0;
$review['purchased_from_microless'] = $wasPurchased;
return $review;
})->all();
Where, the reviews collection is looped through with a check to see if the review's user's orders has an product which has the id of the product in question.
Return true if the count is greater than one.

Laravel 5: Count product by category where active product only

In Laravel 5.4, I have my relationship:
public function products()
{
return $this->hasMany(Product::class);
}
public function category()
{
return $this->belongsTo(Category::class);
}
And my query is:
$x = Category::with('products')->where('active', 1)->get();
It does show all category names correctly, but how to count only product 'active = 1'? I don't wish to count all products, but active products only.
try this:
$x = Category::with(['products' => function($query) { $query->where('active','=', 1); }])->where('active', 1)->get();
That will give you products that are active and then only categories where products are active.
Try this to be more specific. Additional from idea of #linuxartisan
$x = Category::whereHas('products', function ($query) {
$query->where('products.active', '=', 1);
})
->where('categories.active', '=', 1)
->get();
I am assuming you have active field for product as well as category.
Just try this query
$x = Category::whereHas('products', function ($query) {
$query->where('products.active', 1);
})->where('categories.active', 1)
->get();
public function products()
{
return $this->hasMany(Product::class)->where('active',1);
}
This is working in Laravel 7

Laravel 4 unable to retrieve value from belongsTo relation using query builder

I have two tables, organizations and categories. This is how my tables and models are set up:
Tables:
organizations
id - integer
category_id - integer, fk
name - string
...
categories
id - integer
name - string
Models:
class Organization extends Eloquent
{
public function category()
{
return $this->belongsTo('Category');
}
public function comments()
{
return $this->morphMany('Comment', 'commentable');
}
}
class Category extends Eloquent
{
public $timestamps = false;
public function organization()
{
return $this->hasMany('Organization');
}
}
In my routes.php file, I have the following code (where $category is equal to "organizations"):
$query = Organization::query()
->join('categories', 'categories.id', '=', $category . '.id')
->select('categories.name as category');
$tiles = $query->get();
In my view, I am able to perform the following actions without any errors:
foreach($tile->comments as $comment)
{
...
}
...
$tile->name;
However, calling $tile->category->name will give me the error Trying to get property of non-object. And calling $tile->category will just return null. How can I display the category associated with the organization? I am able to retrieve other properties and relations just fine, but this is giving me a problem.
You have a bug in your code: $category . '.id' should be $category . '.category_id' doing so should make $tile->category->name work.
Also please note (you probably already know this) that in the code that you provided you are not actually using the belongsTo relation as set in your Organization class, you are just using the joined data.
The following would also work using the Eloquent ORM utilizing the models relationship methods:
$tiles = Organization::with('category')
->get();
foreach ($tiles as $tile)
{
echo $tile->name . '<br>';
echo $tile->category->name . '<br>';
}
Or you could do so the other way round from the categories model like so:
$tiles = Category::with('organization')
->get();
foreach ($tiles as $tile)
{
echo $tile->name . '<br>';
foreach($tile->organization as $org)
{
echo $org->name . '<br>';
}
}

Resources