Nested eager loading in where clause in Laravel - orm

I want to know is there anyway to write query like this in Laravel using Eloquent. I mean can i do eager loading in where clause. I am stuck here from last day and i really want to do like this. So suggestions needed.
$notifications = Notification::where('user_id',Auth::user()->id)
->where('is_try', '!=', Config::get('constants.NOTIFICATION_AGAINST_JOB_TURN_DOWN'))
->where('is_try', '!=', Config::get('constants.NOTIFICATION_AGAINST_JOB_EXPIRED'))
->where(function($query) {
$query->where(function($query) {
$query->where('message', '!=', 'job_post')
->with(['suggestion' => function ($query) {
$query->with(['job' => function ($query) {
$query->with('company');
}]);
}]);
})
->orWhere(function($query){
$query->where('message','job_post')
->with(['job' => function ($query) {
$query->with('company');
}]);
});
})
->orderBy('notifications.created_at','desc')
->get();

as per my knowledge, you can load the the relationship like this $query->load('company'); instead of $query->with('company');
also you can load multiple/nested relationship like this.
Notification::with([
'rel'=>function($q){ $q->where()... //can add up where, orderby etc clauses like this},
rel.profile,
rel.profile.images,
rel.profile.images.location
])->wehre()....
also you can do this,
$course_orignal = Courses::find($course_id);
$course_orignal->load('quizzes','quizzes.questions', 'chapters','chapters.quizzes.questions','chapters.lessons','chapters.lessons.quizzes','chapters.lessons.quizzes.questions');

Related

How to make a SUM() with WHERE in HASMANY relationship on laravel? Any help is appreciated

Good evening friends, I'm having difficulty on get a SUM from a HASMANY relationship with a condition.
I was trying to do something like this:
$marketPlaces = ModelAccountMarketplace::with(['orders'])
->whereHas('orders', function ($query) use ($dates) {
$query->selectRaw('SUM(valor_frete) as somaFreteGratis')
->whereBetween('datetime', [$dates['dateStart'], $dates['dateEnd']]);
});
But when i try to get the value with: var_dump($marketPlace->somaFreteGratis);
I get a null value. I try to put the where inside the WITH() like:
$marketPlaces = ModelAccountMarketplace::with(['orders' => function ($query) {
$query->selectRaw('SUM(valor_frete) as somaFreteGratis')->where('tipo_frete', 'gratis');
}])
->whereHas('orders', function ($query) use ($dates) {
$query->whereBetween('datetime', [$dates['dateStart'], $dates['dateEnd']]);
});
But in every try i get a null value when i check with:
<?= var_dump($marketPlace->somaFreteGratis); ?>
Any help would be appreciated.
What you're trying to do can be accomplished using a withCount along with a Closure
$marketPlaces = ModelAccountMarketplace::withCount([
'orders as somaFreteGratis' => function ($query) use ($dates) {
$query->select(DB::raw('sum(valor_frete)')
->where('tipo_frete', 'gratis')
->whereBetween('datetime', [$dates['dateStart'], $dates['dateEnd']]);
}
])
->get();

What would be the best way to write this query in Laravel Eloquent?

I'm using this query to get count of clicks, conversions, payout and revenue from an offer.
Now the issue is the query is taking around 1 minute to run for 26 offers and around 15k click overall.
Here is my query
$offers=Offers::select('offer_id','offer_name','offer_currency')
->with(['currency' => function ($query) {
$query->select('currency_id', 'currency_symbol');
}])
->when($request->filter_offer, function($query) use ($request){
return $query->where('offer_id', $request->filter_offer);
})
->whereHas('clicks', function($q) use ($date_from,$date_to){
$q->whereBetween('created_at', [$date_from, $date_to]);
})
->withCount(['conversions'=> function($q) use ($date_from,$date_to){
$q->whereBetween('conversion_date_time', [$date_from, $date_to]);
}])
->withCount(['clicks'=> function($q) use ($date_from,$date_to){
$q->whereBetween('created_at', [$date_from, $date_to]);
}])
->withCount(['conversions AS payout' => function ($query) use ($date_from,$date_to) {
$query->select(DB::raw("SUM(conversion_payout) as payout"))
->whereBetween('conversion_date_time', [$date_from, $date_to]);
}])
->withCount(['conversions AS revenue' => function ($query) use ($date_from,$date_to) {
$query->select(DB::raw("SUM(conversion_revenue) as revenue"))
->whereBetween('conversion_date_time', [$date_from, $date_to]);
}])
;
return Datatables::of($offers)->make(true);
Now this report is dynamic, User can generate the report on the basis of dates and the offer. This application will have more than 100 offers and more than 100million clicks. That time this gonna take a lot of time to generate this report.
What would be the best way to write this query?

Get resultat data from an array

I'm using Laravel and I've used this query to fetch records:
<?php
foreach ($connectionUser as $value) {
if ($value->sender_profile_id == $profile_id) {
//$profileID[] = $value->receiver_profile_id;
$result[] .= $this->select('assets.id', 'assets.profile_id', 'assets.access', 'assets.name', 'assets_data.path', 'assets.processed'
->join('assets_data', 'assets.id', '=', 'assets_data.asset_id')
->where('profile_id', '=', $value->receiver_profile_id)->orderBy('assets.created_at', 'desc')
->get();
} elseif ($value->receiver_profile_id == $profile_id) {
//$profileID[] = $value->sender_profile_id;
$result[] .= $this->select('assets.id', 'assets.profile_id', 'assets.access', 'assets.name', 'assets_data.path', 'assets.processed')
->join('assets_data', 'assets.id', '=', 'assets_data.asset_id')
->where('profile_id', '=', $value->sender_profile_id)
->orderBy('assets.created_at', 'desc')
->get();
}
}
And the result look like this (print_r($result))
Array (
[0] => []
[1] => [{"id":233,"profile_id":175,"access":"PUB","name":"99","path":"Capture_233.PNG","processed":"0"}]
[2] => []
)
How can I get the result datas?
From the code you post, I guess you are trying to retrieve id, profile_id, access from assets table. For question,
any alternative way in laravel to execute above query?
It's better use to eloquent ORM instead of using raw queries. All what you have to do is define the the relationships in the model classes and use the related models as properties.
Check the Laravel Document
Getting Started with Eloquent
Eloquent Relationships
You should check the array result from the query, and check if there is a result, then you push it to $result.
To get the data after finishing that code, you can loop to the $result values (which it will be another array, if you want one result from the query you can take the first on ->first()).

Cakephp 3 - order by two columns with is null

Currently, I'm having a problem with sorting on two columns simultaneously in one particular table. In this case, it is required to sort on particular column (modified_timeline) but when this column is null I want to use the timestamp of another column to sort (created). I have the following query:
return $this->find()
->contain([
'Comments' => function ($q){
return $q
->contain(['Users' => function ($q) {
return $q->select($this->select);
}])
->order(['Comments.created' => 'ASC']);
},
'Users' => function ($q) {
return $q->select($this->select)
->contain(['Pictures' => function ($q) {
return $q->where(['Pictures.profile_photo' => true]);
}]);
},
'Albums'
])
->matching('Albums.Users', function ($q) use ($userId) {
return $q->where(['Users.id' => $userId]);
})
// This particular line:
->order([
'Pictures.modified_timeline' => 'DESC',
'Pictures.created' => 'ASC'
]);
This works only works partially in a way that it doesn't take into account that the modified_timeline can be null. I was thinking to use a case expression to solve this problem but I'm not really understanding how to apply the isNull() function inside a case expression. The following SQL code explains what I want:
ORDER BY
CASE
WHEN Pictures.modified_timeline is null
THEN Pictures.created
ELSE Pictures.modified_timeline
END
My question therefore is how to create the SQL code above with the Cakephp 3 query builder?
This query produce the sql as yo mentioned above :
->order(function ($exp, $q) {
return $exp->addCase(
[
$q->newExpr()->eq('modified_timeline', null),
//$q->newExpr()->gt('modified_timeline', 0), // or you may change condition here
],
['Pictures.created','Pictures.modified_timeline'], // values matching conditions
['string', 'string'] // type of each value (optional)
);
For more details : see cakephp documentation.

Laravel Eloquent Filter By Column of Relationship

Using the Eloquent ORM I have my models set up like so: Post belongsToMany Category
Post.php
public function categories()
{
return $this->belongsToMany('Category', 'posts_categories');
}
I want to filter posts by a column of the categories relationship.
So I want to do something like:
$posts->where('categories.slug', '=', Input::get('category_slug'));
This doesn't work though.
I also tried:
$with['categories'] = function($query){
$query->where('slug', '=', Input::get('category_slug'));
};
$posts::with($with)->get();
But I thnk that's for filtering the categories not filtering BY the category.
Can anyone show me the way?
I can't access my Vagrant box right now, but I believe this should work:
$posts = Post::whereHas('categories', function($q)
{
$q->where('slug', '=', Input::get('category_slug'));
})->get();
Here's a quick way to filter on related model column:
$allConsultants = Consultant::whereHas('user', function($query)
{
$query->where('is_approved', '=', 1);
})->get();