Order by relevance based on multiple conditions using Laravel - php

I am having an issue while using order by based on multiple conditions.
User with most filled information should show up top and then the one's with less filled information.
$users = User::where('status',1)
->withCount('reviews')
->with('reviews','about')
->orderByRaw("CASE WHEN is_native != '0' AND photo != '' THEN 0 ELSE 1 END")// how i can match the about us relationship value here? means if user have added about intro then it should come first and reviews count?
->paginate(10);
Here is my About Relationship on User
public function about()
{
return $this->hasOne('App\UserAbout', 'user_id')->select('about');
}
NOTE: i am trying to do it with CASE, if there is any other good option you can please point out that.
Thank you

this means that you have to orderby about's count and then by review count, that will get the result you want:
$users = User::where('status',1)
->withCount(['reviews','about'])
->with('reviews','about')
->orderByRaw('about_count desc,reviews_count desc')
->paginate(10);
now user with 'about' will have about_count=1 others will have about_count =0

As #OMR suggested you can do that. But you don't need to use raw Query
$users = User::where('status',1)
->withCount(['reviews','about'])
->with('reviews','about')
->orderBy('about_count','desc')
->orderBy('reviews_count','desc')
->paginate(10);

Related

How to implement eloquent where has relationship with specific condition?

i have a case where i need to filter results by condition in 1-n relationship
so i have this 1-n relationship in User.php
public function permits()
{
return $this->hasMany('App\Permit');
}
result i want to retrieve is users where all permits are expired (expiry on permits table = 0), because 1 user can own many permits, and the condition i need to met is from all their permits they must be expired
my current query is like this, this pulled several hundred wrong data because i didn't understand yet how to implement where all permits expiry = 0
$users = User::where('club_id',$this->id)->whereHas('permits',function($q){
$q->where('expiry','<=','0');
})->get();
current solution which is bad solution (longer time to execute), just so you guys clearer with what i want to achieve
foreach($users as $key => $user){
foreach($user->permits as $permit){
if($permit->expiry > 0){
$users->forget($key); // unset from the users collection
break;
}
}
}
any help would appreciated thank you!
If you want users where all permits are expired
We can achieve this from whereDoesntHave() function.
$users = User::where('club_id',$this->id)
->whereDoesntHave('permits', function($query){
// query for not expired.
// I believe the column expiry value is 0 when premit is not expired.
$query->where('expiry', 0);
})
->get();
Technically what we did was get users where doesn't have non expired permits. Literally that means all permits are expired.

Laravel Eloquent: Select where related table has x, but exclude certain rows from related table

Im trying to return a collection from the database that houses a 'User Group' as well as its related users. However, I want the selection criteria to be based on whether or not a user in the related table is trained or not. If this is the case, I want that row/entry to be EXCLUDED from the final collection.
Essentially, I want to:
Return all groups of type 'GreenGroup' where at least one related employee is untrained, and show only untrained employees in the table.
Such that it would return an object like this:
0: {
id: 2,
group: GreenGroup,
size: 4,
employees: {
0: {name: 'Jane', isTrained: 0},
1: {name: 'Jeremy', isTrained: 0}
}
}
But right now, it is finding the GreenGroup, but returning ALL users in that group. I am looking for a way to exclude them in the query builder. So far, this is what I have:
$results = Group::with(['employees'])->where('group', '=', 'GreenGroup')->whereHas('employees', function($query){
$query->where('isTrained', '=', '0');
})->get();
return json_encode($results);
Is there a way to exclude relational table entries in the querybuilder? Or am I forced (when I loop through these and display them on my site) to write logic that checks if they're trained or not?
You need to change your query like I mentioned below:
$results = Group::with(['employees' => function($query){
$query->where('isTrained', '=', '0');
}])->where('group', '=', 'GreenGroup')->get();
return json_encode($results);
The query which you mentioned will return always all the members because you set condition in whereHas not in with.
The query you wrote is mainly used to get all the groups with nontrained members ( for this you need to remove where('group', '=', 'GreenGroup') ) but you want something opposite, so you need to set condition in With.

CodeIgniter - Count rows active record joint

I'm trying to better understand how CI works.
This is my first table, app_news:
id / name
My second is app_news_comments:
id / id_news / comment
The model I use in order to display news informations is:
public function get_news($where = array()) {
return $this->db->select('*')
->from('app_news')
->where($where)
->get()
->result();
}
The model I use in order to count comments for a news is:
public function count_comment($id_news) {
return (int) $this->db->where(array('id_news' => $id_news)
->count_all_results('app_news_comments');
}
The first solution I have is to print a foreach on my view and putting the count_comment function inside the loop in order to count how much comments I have however I won't respect the MVC pattern. How can I do so ?
The best way to get that information is using this query:
SELECT
app_news.id,
app_news.name,
COUNT(app_news_comments.id)
FROM app_news_comments
JOIN app_news ON app_news_comments.id_news = app_news.id
GROUP BY app_news_comments.id_news
So, you need to create a query using Active Record on Codeigniter or you could add the directly, because Active Record on Codeigniter have some restrictions.
However, you could use this way on Codeigniter to create the query:
$this->db->select('[YOUR FIELDS AND COUNT]', FALSE)
->from('app_news_comments') .... etc
and to add the query directly:
$this->db->query('[QUERY HERE]');
I hope this help you.

Adding two where conditions in laravel

I know to check how to fetch a particular item in laravel like
$PackCount = PackModel::where('PackId', Input::get('packid'))->count();
But how can i check whether the items are matches another two coloumn i.e.,
where condition for IsActive and IsAvailable ?
If you want to have more where in your Query then just do
$PackCount = PackModel::where('PackId', Input::get('packid'))->where('IsActive', '=', '1')->where('IsAvailable', '=', '1')->count();
Read more about Advance Where here
Try this..
$count = PackModel::where('PackId', Input::get('packid'))->where('IsActive', '1')->where('IsAvailable', '1')->count();

Counting total distant relationships in Laravel (eager loading?)

I'm having issues getting a proper count total with my Laravel model.
Model Structure
User
Item
ItemLike
A user can have multiple Items, and each of these Items can have multiple ItemLikes (when a user 'likes' the item).
I can easily get the individual ItemLike counts when using an Item model:
return $this->itemLikes()->count();
But I can't figure out how to get the total # of ItemLike's a User has across all the Item's he owns.
EXAMPLE
User A has 3 Items. Each Item has 5 ItemLike's, for a grand total of 15.
I tried using eager loading on the User model like this:
return $this->items()->with('itemlikes')->get()->count();
But that returns 3 (the # of Items)
These are the queries it ran, which appears like the second query is the one I want, yet every way I try it I still get 3 instead of 15
select * from `items` where `items`.`user_id` = '1000'
select * from `item_likes` where `item_likes`.`item_id` in ('1000', '1001', '1002')
After suggestions from others I found 2 solutions to get the result.
Using whereIn:
$itemViewCount = ItemView::
whereIn('item_views.item_id', $this->items()->lists('id'))
->count();
return $itemViewCount;
2 queries for a total of 410μs
Using join:
$itemViewCount = $this->items()
->join('item_views', 'item_views.item_id', '=', 'items.id')
->count();
return $itemViewCount;
2 queries for a total of 600μs
Isn't it just a case of creating a method that would return the number of items for the model. e.g.:
#UserModel
public function nbLikes()
{
$nbLikes = 0;
foreach($this->items() as $item) {
$nbLikes += $item->itemLikes()->count();
}
return $nbLikes;
}
And then User::nbLikes() should return the piece of data you are looking for?
try this:
$query="select count(il.id) from item_likes il,item itm where il.item_id=itm.id and tm.user_id=1000";

Categories