Laravel 4/5, order by a foreign column - laravel

In Laravel 4/5 how can order a table results based in a field that are connected to this table by a relationship?
My case:
I have the users that only store the e-mail and password fields. But I have an another table called details that store the name, birthday, etc...
How can I get the users table results ordering by the details.name?
P.S.: Since users is a central table that have many others relations and have many items, I can't just make a inverse search like Details::...

I would recommend using join. (Models should be named in the singular form; User; Detail)
$users = User::join('details', 'users.id', '=', 'details.user_id') //'details' and 'users' is the table name; not the model name
->orderBy('details.name', 'asc')
->get();
If you use this query many times, you could save it in a scope in the Model.
class User extends \Eloquent {
public function scopeUserDetails($query) {
return $query->join('details', 'users.id', '=', 'details.user_id')
}
}
Then call the query from your controller.
$users = User::userDetails()->orderBy('details.name', 'asc')->get();

Related

Laravel Lumen eloquent left join returns joined table data rather than primary able data

I have two tables company and courses table
The table has the following fields
companies table
id, full_name, email, deleted_at
and courses table
courses table
id, company_id, course_name,deleted_at
Now i would like to retrieve all courses which company is not deleted. So in my controller i have added
public function index(Request $request){
$query = Courses::query();
$query = $query->leftJoin('companies','companies.id','=','courses.company_id');
$query->whereNull('companies.deleted_at');
if($request->get('filter_name')){
$query = $query->where('courses.name', 'like', '%' . $request->get('filter_name') . '%');
}
return response()->json($query->paginate($request->get("perPage")));
}
When i run the above it returns companies data rather than courses. Where am i going wrong or what am i missing out?
If you have use eager loading in both of your model, you can use this kind of approach.
$all_course = Courses::with(['company', function($query) {
return $query->whereNotNull('deleted_at');
}])->get();
As you can see, I query in the Courses model to return all the courses but I added some filter in the company relationship. where in I used whereNotNull to get only the company that's not deleted.

laravel eloquent with pivot and another table

I have 4 table categories, initiatives, a pivot table for the "Many To Many" relationship category_initiative and initiativegroup table related with initiatives table with initiatives.initiativesgroup_id with one to many relation.
With pure sql I retrive the information I need with:
SELECT categories.id, categories.description, initiatives.id, initiatives.description, initiativegroups.group
FROM categories
LEFT JOIN category_initiative ON categories.id = category_initiative.category_id
LEFT JOIN initiatives ON category_initiative.initiative_id = initiatives.id
LEFT JOIN initiativegroups ON initiatives.initiativegroup_id = initiativegroups.id
WHERE categories.id = '40'
How can I use eloquent model to achieve same results?
Since you have such a specific query touching multiple tables, one possibility is to use query builder. That would preserve the precision of the query, retrieving only the data you specifically need. That would look something like this:
$categories = DB::table('categories')
->select([
'categories.id',
'categories.description',
'initiatives.id',
'initiatives.description',
'initiativegroups.group',
])
->leftJoin('category_initiative', 'categories.id', '=', 'category_initiative.category_id')
->leftJoin('initiatives', 'category_initiative.initiative_id', '=', 'initiatives.id')
->leftJoin('initiativegroups', 'initiatives.initiativegroup_id', '=', 'initiativegroups.id')
->where('categories.id', '=', 40)
->get();
In your models define the relationships:
Category.php model
public function initiatives()
{
return $this->belongsToMany('App\Initiative');
}
Initiative.php model (If has many categories change to belongs to many)
public function category()
{
return $this->belongsTo('App\Category');
}
Then maybe change your initiativegroup -> groups table, and then create a pivot table called group_initiative. Create model for group. Group.php and define the relationship:
public function initiatives()
{
return $this->belongsToMany('App\Initiative');
}
Then you can also add the following relationship definition to the Initiative.php model
public function group()
{
return $this->belongsTo('App\Group');
}
That should get you started.
for the record..
with my original relationship, but changing table name as alex suggest, in my controller:
$inits = Category::with('initiative.group')->find($id_cat);
simple and clean

how to get list of users who are not under belongsToMany relation under a table in laravel?

Consider the following case.
we have the Users table and Tasks table. they are in relation with belongsToMany with table task_user.
How to get the list of all users who are not under any task? i.e. their user_id is not at all under that given task or even in the task_user table.
why I need this is because like this we can only provide a list of users who are yet to be assigned a task. the task will be assigned to users and not a single user at a time.
Editing_____________
also how to filter with users based on group table? below is not working
$users = Group::with(['subscribers' => function ($q){
$q->doesntHave("tasks");
}])->whereId($gid)->latest()->get();
Assuming you've named your relationships properly, you should be able to use doesntHave("tasks"):
$tasklessUsers = User::doesntHave("tasks")->get();
doesntHave() checks for the non-existence of the supplied relationship ("tasks", in this case) and returns all objects that pass this check.
If your function name is different, use that, but the relationship should be:
User.php:
public function tasks(){
return $this->belongsToMany(Task::class, "task_user");
}
Edit: doesntHave() is the simple version, whereDoesntHave() allows a custom query. See https://laravel.com/docs/5.8/eloquent-relationships#querying-relationship-absence for full details.
Second Edit:
As stated in the comments below, with() will not filter the Model it is being called on, so this query won't work as you'd expect:
$users = Group::with(['subscribers' => function ($q){
$q->doesntHave("tasks");
}])->whereId($gid)->latest()->get();
To fix this, use a chained doesntHave() query:
$query = Group::doesntHave('subscribers.tasks')
->where('id', '=', $gid)
->latest()
->first();
// OR
$query = Group::whereHas('subscribers', function($subQuery){
$subQuery->doesntHave('tasks');
})->where('id', '=', $gid)
->latest()
->first();
$users = $query->subscribers; // Return `users` (aliased to `subscribers`)
Either approach will check the existence of subscribers that don't have any associated tasks relationship, and also only return where id is $gid.
Note: Used first() for the queries, as using id in a query should only ever return a single Group record, and get() is for returning multiple records in a Collection

Why is the ID replaced with a value from another table? Laravel BelongsTo

I have 4 tables. Championships, Users, Roles and users_roles.
One user belongs to championship as judge. But I have to select only users who have role 'Judge'.
For this, I created new column in championships table which is called "main_judge" and created new relationship
class Championship extends Model
{
...
public function mainJudge()
{
return $this->hasOne('App\User', 'id', 'main_judge');
}
...
}
Then I add to query some code
$query->join('users_roles', 'users.id', '=', 'users_roles.user_id')
->join('roles', 'users_roles.role_id', '=', 'roles.id')
->where('roles.alias', '=', 'judge');
when I print query as sql I got (see screen)
http://joxi.ru/a2X45M1Sw0RpE2
and after $query->get() instead of user ID i got a role ID (see screen)
http://joxi.ru/bmoxMaDs3NVoE2
I would suggest using eloquent rather than the query builder as it will remove the need to manually define any joins.
You should just be able to do this:
$championship = Championship::find($id);
$judge = $championship->mainJudge;
If you then dd($judge) you should end up with the appropriate User object.

Laravel, How to retrieve parent records with certain Pivot table values belongsToMany

How can I retrieve all records of my model based on certain ID's in my pivot table?
I have the following 3 tables
users;
id,
name
stats;
id,
name
stats_selected;
user_id,
stats_id
Model
User.php
public function stats()
{
return $this->belongsToMany('App\stats', 'stats_selected', 'user_id', 'stats_id')->withTimestamps();
}
Controller
// Get all users with example of stats ID's
$aFilterWithStatsIDs = [1,10,13];
$oUser = User::with(['stats' => function ($query) use($aFilterWithStatsIDs ) {
$query->whereIn('stats_id', $aFilterWithStatsIDs);
}])
->orderBy('name', 'desc')
->get()
This outputs just all the users. Btw, fetching users with there stats and saving those selected stats into the DB is not a problem. That works fine with the above lines.
But how do I retrieve only the users which has certain stats_id's within them?
But how do I retrieve only the users which has certain stats_id's within them?
Use a whereHas conditional.
User::whereHas('stats', function ($stats) use ($aFilterWithStatsIDs) {
$stats->whereIn('id', $aFilterWithStatsIDs);
});

Resources