How create a subquery with eloquent and laravel with softdeletes - laravel

I am using Laravel 7 and Vue.js 2.
I want to retrieve the tasks that are not assigned to a specific user.
I made the following code that works correctly.
$tasks_user = TaskUser::select('task_id')
->where('user_id', $id)
->get();
$tasks = Task::select('tasks.id as id', 'tasks.name as name', 'tasks.description as description')
->join('task_user', 'tasks.id', '=', 'task_user.task_id')
->whereNotIn('task_user.task_id', $tasks_user)
->distinct()
->get();
By the way to be more elegant I decided to transform the above code into a single query as follows:
$tasks = Task::select('tasks.id as id', 'tasks.name as name', 'tasks.description as description')
->join('task_user', 'tasks.id', '=', 'task_user.task_id')
->whereNotIn('task_user.task_id', function($q) use ($id)
{
$q->select('task_id')
->from('task_user')
->where('user_id', $id)
->get();
})
->distinct()
->get();
Unfortunately I discovered that the above query didn't work because it doesn't considers softdeletes.
For example, if the user with id 3 was related with the task 7 but now that row has been deleted with softdeletes in the table task_user, the first code returns also the task with id 7 (correctly) and the second one not (uncorrectly).
So finally, I must do a single query that works as the first code.
Can help?

You can actually combine both approaches. whereNotIn accepts also an Eloquent Query, it doesnt need to be a callback. Try this:
$userRelatedTasksQuery = TaskUser::select('task_id')
->where('user_id', $id);
$tasks = Task::select('tasks.id as id', 'tasks.name as name', 'tasks.description as description')
->join('task_user', 'tasks.id', '=', 'task_user.task_id')
->whereNotIn('task_user.task_id', $userRelatedTasksQuery)
->distinct()
->get();
Be sure to not use get() at the end of the $userReleatedTasksQuery, as you want the eloquent query instance, not the result.

Related

Laravel Query Builder result using join() query

The following query works fine, but the problem is that it gives the id of the events table instead of tasks table id in the output result.
Task::join('events', function ($join) {
$join->on('events.task_id', '=', 'tasks.id')
->where('events.event_type', '=', 'Task')
->where('events.task_stage', '!=', 'assigned');
})->select('tasks.*')
->get();
Try this, one should work
->select('*', 'tasks.id as taskID')->get();
This is because maybe both tasks and events table have id field. So u need to use a separate query to specify the id.
try this one
use mysql alias here
Task::join('events', function ($join) {
$join->on('events.task_id', '=', 'tasks.id')
->where('events.event_type', '=', 'Task')
->where('events.task_stage', '!=', 'assigned');
})->select('tasks.*','tasks.id as taskId')->get();

Laravel distinct on join results not working in query builder

I have a posts table that has join query with 4 other tables. 3 of them are one to one relations but the 4th is one to many. I want the query to return only 1 row for each post. What i am trying so far is like this-
$query = DB::table('posts')
->select('posts.*',
'subcategories.subcategory_title_en',
'subcategories.subcategory_title_bn',
'categories.category_title_en',
'categories.category_title_bn',
'users.*',
'postimages.postimage_thumbnail'
)
->join('subcategories', 'subcategories.subcategory_id', '=', 'posts.subcategory_id')
->join('categories', 'categories.category_id', '=', 'subcategories.parent_category_id')
->join('users', 'users.id', '=', 'posts.user_id')
->join('postimages', 'postimages.post_id', '=', 'posts.post_id');
$query->groupBy('posts.post_id');
echo $query->count();
exit();
I have currently 50 posts in database, but the query returns all rows for each postimages, more than 1 row for each post that is. I thought distinct would only show each post_id once? What am i missing here?
I would prefer if someone tells me how to do this with query builder. As this will have a lot of searching on different columns and i want it to be as fast as possible.
This is a simpler version -
$query = DB::table('posts')
->select('posts.*','postimages.postimage_thumbnail')
->join('postimages', 'postimages.post_id', '=', 'posts.post_id')
->groupBy('posts.post_id');
echo $query->count();
exit();
The strange thing is the SQL query that is shown by laravel " select posts.*, postimages.postimage_thumbnail from posts inner join postimages on postimages.post_id = posts.post_id group by posts.post_id" works fine in mysql
You should use groupby
Try this code
$query = DB::table('posts')
->select('posts.*',
'subcategories.subcategory_title_en',
'subcategories.subcategory_title_bn',
'categories.category_title_en',
'categories.category_title_bn',
'users.*',
'postimages.postimage_thumbnail'
)
->join('subcategories', 'subcategories.subcategory_id', '=', 'posts.subcategory_id')
->join('categories', 'categories.category_id', '=', 'subcategories.parent_category_id')
->join('users', 'users.id', '=', 'posts.user_id')
->join('postimages', 'postimages.post_id', '=', 'posts.post_id')->groupBy('posts.post_id');
In config/database.php at "mysql" change : 'strict' => true, to false

Laravel 5.2 Eloquent Order Query by Eagerly Loaded Data

Is it possible to order the results of an Eloquent query by the eagerly loaded data. To be clear I get the right data, it is paginated properly, and works in every way except it isn't ordered the way I need it to be. In this case I'd like to sort users by profile.firstname.
Something like this:
$results = User::where('id', '!=', $user->id)
->whereNotIn('id', $ids)
->with([
'profile' => function ($query) {
$query->addSelect(['id', 'first_name', 'last_name']);
},
])
->orderBy('profile.first_name', 'desc')
->paginate();
The data is used in an Ionic application and is used for an infinite scroll so I need to have the data in the format below ordered by first_name prior to being received on the client, but the above example doesn't work.
DATA needed for Ionic View
user: {
id: '1',
username: 'aUsername'
email: 'anEmail'
profile: {
id: '2',
user_id: '1',
first_name: 'aFirstName',
last_name: 'aLastName',
phone_number: '999-999-9999'
}
}
...
Solution (with flattened result set)
$results = User::join('user_profiles', 'users.id', '=', 'user_profiles.user_id')
->select('users.id', 'users.username', 'user_profiles.first_name', 'user_profiles.last_name')
->where('users.id', '!=', $user->id)
->whereNotIn('id', $existingContactIds)
->where('users.username', 'like', $request->input('username') . '%')
->orderBy('user_profiles.first_name')
->paginate();
Solution (with proper result format)
$results = User::where('users.id', '!=', $user->id)
->whereNotIn('users.id', $existingContactIds)
->where('users.username', 'like', $request->input('username') . '%')
->with([
'profile' => function ($query) use ($columns) {
$query->addSelect('user_profiles.first_name', 'user_profiles.last_name');
},
])
->select('users.id', 'users.username')
->join('user_profiles', 'users.id', '=', 'user_profiles.user_id')
->orderBy('user_profiles.first_name')
->paginate();
For ordering by another table, you need to perform a join.
Chain in a join for your profile table
-> join('profiles', 'profiles.id', '=', 'users.profile_id')
You'll then be able to orderBy first_name (though not profile.first_name).
It isn't possible to orderBy eager loaded tables. If you look at the SQL Laravel produces, you'll see that it firsts gets all the results from the users tables then passes the IDs of just the results (so a subset of all results if you're using pagination) to the profiles table to get relevant data.
You could sometimes avoid the join by using the Collection method sortBy on the results, but this won't work when coupled with pagination as sortBy only works on the results, so will be ordering a subset of data only (but sortBy does support the dot notation you've tried using for your orderBy).
Im seeing your code and I think it should be ->orderBy('profile->first_name', 'desc') or try this other way ->orderBy('first_name', 'desc')
Try like this
$results = User::where('id', '!=', $user->id)
->whereNotIn('id', $ids)
->with([
'profile' => function ($query) {
$query->addSelect(['id', 'first_name', 'last_name']);
$query->orderBy('first_name','DESC');
},
])
->paginate();

how to select particular user id in laravel?

i have tried the below code to calculate the attendance of a particular user but calculations is happening for all the users available in the table. I'm new to laravel so i need help.
in the controller:
$TController =DB::table('tbl_attendancetime')
->select('username','statusid','status_description','user_id')
->groupby('username')
->get();
$TController1 =DB::table('tbl_attendancetime')//->distinct()
->select('statusid')
->where('statusid','=', 0)//->groupBy('user_id')
->get();
$TController2 =DB::table('tbl_attendancetime')
->select('statusid')//->groupby('user_id')
->where('statusid','=', 1)//->distinct()->get(array('user_id'));
//->groupBy('user_id')
->get();
$TController3 =DB::table('tbl_attendancetime')
->select('status_description')//->groupby('user_id')
->where('status_description','=',3)
->groupBy('user_id')
->get();
$TController4 =DB::table('tbl_attendancetime')
->select(
'status_description')//->groupby('user_id')
->where('status_description','4')
->groupBy('user_id')
->get();
$TController5 =DB::table('tbl_attendancetime')
->select(
'status_description')//->groupby('user_id')
->where('status_description','5')
->groupBy('user_id')
->get();
foreach($TController as $row)
{
$a=count($TController1);
$p=count($TController2);
$e=count($TController3);
$s=count($TController4);
$su=count($TController5);
}
In your first query , in where condition you used this line
->where('tbl_attendancetime.user_id', 'create_register.user_id')
for this reason, you get all information for the user id which are presented on both tbl_attendancetime & create_register.
If you want particular user information, use specific ID.
For example
->where('tbl_attendancetime.user_id', 1)

Eloquent User Where Clause with Entrust Library

I'm trying to select all users for a company. But only users who has "admin" role status (Entrust, etc.).
User::where('company_id', Auth::user()->company_id)->hasRole('admin')->get();
The above is throwing an error. Left a bit lost on how to run such a query. Where am I going wrong with this? Very little documentation on Entrust.
You can use plain Eloquent for this. The whereHas method would generate one query:
$users = User::where('company_id', Auth::user()->company_id)
->whereHas('roles', function($query) {
$query->where('name', 'admin');
})->get();
Or, you can just get the roles and then get all of that role's users. This would generate two queries, but ultimately achieve the same thing.
$users = Role::where('name', 'admin')
->first()
->users()
->where('company_id', Auth::user()->company_id)
->get();
Think you need to get all the users having the company_id first
$users = User::where('company_id', Auth::user()->company_id)->get();
Then loop through $users and check hasRole()
foreach ($users as $user) {
if($user->hasRole('admin')){
//user is admin
}
}
UPDATE
This might be a dirty solution but you can try to do a manual query
$admin = DB::table('role_user')
->join('users', 'users.id', '=', 'role_user.user_id')
->join('roles', 'roles.id', '=', 'role_user.role_id')
->where('roles.name', 'admin')->get();

Resources