Laravel query/access DB information - php

public function countPeople($id = 0, $country = false)
{
if ($id == 0) {
$s = Group::leftJoin('user_hobbies', 'user_hobbies.hobby_id', '=', 'groups.hobby_id')
->where('groups.hobby_id', $this->hobby_id)
->select(DB::raw('count(user_hobbies.user_id) as count'))
->get()
->first();
} else if ($country) {
$s = Group::leftJoin('user_hobbies', 'user_hobbies.hobby_id', '=', 'groups.hobby_id')
->leftJoin('user_locations', 'user_locations.user_id', '=', 'user_hobbies.user_id')
->leftJoin('cities', 'cities.id', '=', 'user_locations.city_id')
->where('groups.hobby_id', $this->hobby_id)
->where('cities.country_id', $country)
->select(DB::raw('count(user_hobbies.user_id) as count'))
->get()
->first();
} else {
$s = Group::leftJoin('user_hobbies', 'user_hobbies.hobby_id', '=', 'groups.hobby_id')
->leftJoin('user_locations', 'user_locations.user_id', '=', 'user_hobbies.user_id')
->where('groups.hobby_id', $this->hobby_id)->where('user_locations.city_id', $id)
->select(DB::raw('count(user_hobbies.user_id) as count'))
->get()
->first();
}
if ($s) {
return $s->count;
}
return 0;
}
Beginner here.. I'm using another persons code to try to learn/understand a few problems. There exists this function in the controller that counts members in a group, but it doesn't give access to that persons other information, like name, photo.. etc.. Is it possible from this function to use the same function and return it as a view? Would that give me the access to the user information?
I'm not yet so well informed on how to query the DB so fluently.
Any help useful! thank you.

Since this query returns an aggregate value (count) you won't be able to get any user information from it. However, you could remove the ->select(DB::raw('count(user_hobbies.user_id) as count')) part which would end up returning a Collection with all the information from the joined tables. To get the count from that, just use the Collection's ->count() method.
$groups = Group::leftJoin('user_hobbies', 'user_hobbies.hobby_id', '=', 'groups.hobby_id')
->where('groups.hobby_id', $this->hobby_id)
->get();
#foreach ($groups as $group)
<p>{{ $group->hobby_id; }}</p>
<p>{{ $group->user_id; }}</p>
#endforeach
<p>Count: {{ $groups->count() }}</p>

Related

How do you filter the user with hasRole() in Laravel 5 within relational query?

I want to filter my query and return only if the user hasRole "Premium" and limit the result to 10.
Along with this query is a count of records which Conversion has and sort it in DESC order by total column.
Right now I have a working query that returns the count of Conversion and with a User but without user filter Role.
// Model Conversion belongs to User
// $from & $end uses Carbon::createDate()
// Current code
$query = Conversion::select('user_id',DB::raw('COUNT(*) as total'))
->whereBetween('created_at', [$from,$end])
->where('type','code')
->where('action','generate')
->whereNotNull('parent_id')
->with('user')
->groupBy('user_id')
->orderBy('total', 'DESC')
->take(10)
->get();
// current result
foreach ($query as $q) {
$q->user->name; // To access user's name
$q->total; // To access total count
}
// I tried this but no luck
$query = Conversion::select('user_id',DB::raw('COUNT(*) as total'))
->whereBetween('created_at', [$from,$end])
->where('type','code')
->where('action','generate')
->whereNotNull('parent_id')
->with('user', function($q) {
$q->hasRole('Premium');
})
->groupBy('user_id')
->orderBy('total', 'DESC')
->take(10)
->get();
You need to use whereHas instead of with, like this:
->whereHas('user', function ($query) {
$query->where('role','Premium');
})
Use the whereHas() instead of with(). Also, you can't use hasRole() if it's not a local scope:
->whereHas('user.roles', function($q) {
$q->where('name', 'Premium');
})

Laravel Eloquent non-lambda parameters

I'm trying to retrieve a number of results from database using eloquent.
I dont have problem with that.
Example code
$flights = App\Flight::where('active', 1)
->orderBy('name', 'desc')
->take(10)
->get();
Now lets suppose I have a variable that if it's true i want to add one more WHERE clause. For example if $domestic == true then i want something like this:
$flights = App\Flight::where('active', 1)
->where('domestic',1)
->orderBy('name', 'desc')
->take(10)
->get();
So I dont like to do, because it's not nice.
if($domestic) {
$flights = App\Flight::where('active', 1)
->where('domestic',1)
->orderBy('name', 'desc')
->take(10)
->get();
} else {
$flights = App\Flight::where('active', 1)
->orderBy('name', 'desc')
->take(10)
->get();
}
Ideally i want to pass only the where clause eg.
if(#domestic) { $flights->where('domestic',1) }
But this is not working.
What is the best way to pass additional where clauses whenever needed?
$flights = App\Flight::where('active', 1)
->orderBy('name', 'desc')
->when($domestic, function ($query){
return $query->where('domestic',1)
})
->take(10)
->get();
The laravel query builder has some real gems like the when clause, the when clause will only execute the closure if the first parameter is true (in this case $domestic)
This specific function can be found here. On the same way more of these functions can be found.
Solution is:
$flights = App\Flight::where('active', 1);
if($domestic) {
$flights->where('domestic',1);
}
$results = $flights->orderBy('name', 'desc')
->take(10)
->get();
Use Query Scopes
Write them on your model, quick example on flight model:
public function scopeIsDomestic($query,$domestic){
if($domestic == 1){
return $query->where('domestic',1);
}else{
return $query; //you can return the inverse if you need it -> where domestic <> 1
}
}
And now use it like this
$flights = App\Flight::where('active', 1)
->isDomestic(1)
->orderBy('name', 'desc')
->take(10)
->get();
It provides a nice way to keep the code maintainable since you can update the scope on all your queries at the same time by modifying it on a single place

cant get the data I want from two different tables using Laravel

I have a table called instructor_class: user_id, class_id and I have another table classes: id, time, active.
I would like to show classes for a single user but only those classes that active is 0 or 1.
My current code looks like this:
return InstructorClass::with('classes.session')->where('user_id', '=', $userId)->get();
This code is displaying me everything, then I tried the following code:
$active = 1;
return InstructorClass::with(['classes' => function ($q) use ($active) {
$q->where('active', '=', $active); // '=' is optional
}])
->where('user_id', '=', $userId)
->get();
This again returns me same records, but of course the class property is null for each record, which at some point looks correct, but my point is if the 'active' field does not corresponds at the classes table do not show the record, seems like the where() stm within with() is optional..
I am kinda stuck here...
Would appreciate your help, opinions!
You can use ::has('classes') to only return the models that have related classes
return InstructorClass::has('classes')->with(['classes' => function ($q) use ($active) {
$q->where('active', $active);
}])
->where('user_id', '=', $userId)
->get();
Never thought it could be this simple:
return InstructorClass::with('classes.session')
->join('classes', 'classes.id', '=', 'instructor_class.class_id')
->where('classes.active', '=', 1)
->where('user_id', '=', $userId)
->get();

Laravel: How to search DB for a given string using eloquent?

I would like to retrieve data matching the search string, provided, it must not belongs to current user.
if($str_search && $str_search != '' )
{
$mandate_list = Mandate::select(array('umrn','mandate_status', 'payment_type','currency','fixed_amount','max_amount','user_id','id','debtor_bank','creditor_bank','refusal_reason'))
->orWhere('id', 'LIKE', '%'.$str_search.'%')
->orWhere('umrn','LIKE','%'.$str_search.'%')
->orWhere('mandate_status','LIKE','%'.$str_search.'%')
->orWhere('mandate_date','LIKE','%'.$str_search.'%')
->orWhere('payment_type','LIKE','%'.$str_search.'%')
->orWhere('currency','LIKE','%'.$str_search.'%')
->orWhere('fixed_amount','LIKE','%'.$str_search.'%')
->orWhere('mandate_date','LIKE','%'.$str_search.'%')
->where('user_id', '<>', $current_user)
->orderBy('updated_at', 'desc')
->get();
}
But this query displays all records (even belongs to current user).
How can i solve this. Thanks for your suggestions.
Group all your orWheres in a closure:
Mandate::select([.....])->where(function($query) use ($str_search)
{
$columns = ['id', 'umrn', 'mandate_status', ...];
foreach ($columns as $column)
{
$query->orWhere($column, 'LIKE', '%'.$str_search.'%');
}
})
->where('user_id', '<>', $current_user)
->orderBy('updated_at', 'desc')
->get();

Laravel: Sort Table Joined Using 'With' Clause

I'm using Laravel 4 and Eloquent ORM. I'm currently pulling records from my database using the following code:
public function index($type, $id)
{
$asset = Asset::where('public_id', '=', $id)
->with('attachments')
->with('attachments.attachment')
->with('tracks')
->with('tracks.track')
->where('locale', '=', Config::get('app.locale'))
->first();
return View::make('view-asset.index')
->with('asset', $asset)
->with('type', $type);
}
The table joined to this query using the with('tracks') statement has a column in it called track_order - I would like to be able to sort the rows returned by this part of the query by that column so that the tracks stored in the database are returned in the correct order.
Is it possible to do this and if so, how should I do it? So far I've tried something like this:
public function index($type, $id)
{
$asset = Asset::where('public_id', '=', $id)
->with('attachments')
->with('attachments.attachment')
->with('tracks')
->with('tracks.track')
->where('locale', '=', Config::get('app.locale'))
->orderBy('tracks.track_order', 'ASC')
->first();
return View::make('view-asset.index')
->with('asset', $asset)
->with('type', $type);
}
Which doesn't work and I can't figure out a way of doing this other than splitting things up into multiple queries.
You most certainly can:
with(['tracks' => function($query)
{
$query->orderBy('track_order', 'asc');
}])
Refer to Eager Loading Contraints in the documentation for more.

Categories