HasMany WhereNotIn - laravel

I am creating a query in laravel via models to filter out what is/isnt already in a group.
Models:
Group
GroupMembers
Users
Filters in place:
function members()
Groups->hasMany(GroupMembers)
Trying to achieve this:
Users->whereNotIn(Groups->members())
This is the lines of code in question, how the rest of it is all built I believe to be irrelevant:
$groups = Groups::find($request['id']);
// die($groups->members);
return view('admin.groups.add_member',
['group' => $groups,
'users' => User::whereNotIn('id', $groups->members->user)]);
the die() command returns the lines of the members successfully. The return statement groups->members returns an array of [1,1,1] (this is the group id where there are 3 members of the group)
I am sure its something simple but some help would be appreciated!

Try something like this (assuming the column is called user_id):
User::whereNotIn('id', $groups->members->pluck('user_id'))->get()

Related

Laravel Collection - put specific item on last position

I have database table with different roles and I need collection where items with role owner will be last. Here is database example:
ID
Role
1
admin
2
user
3
user
4
owner
5
user
How can I sort collection with those data to get item with role owner as last? I could only think of sorting it alphabetically, saving to some variable and deleting the record with the owner role from the collection, and then pasting it into the collection as last. But it seems unnecessarily complicated to me, isn't there an easier way?
The reason why I need this is because I need remove all selected users and to be sure that user/owner is the last one.
You Can Use Conditional rendering. For That you need to use DB::raw
Example:
Model::select('id', 'role')
->orderBy(DB::raw('role = "owner"'), 'ASC');
Or Use shorthand:
Model::select('id', 'role')->orderByRaw("role = 'owner' ASC");
It will place owners At the end.
Check Fiddle here: http://sqlfiddle.com/#!9/9d2b64/2
For eloquent, you can use sortBy() method with array_search() :
$collection = Model::get();
$data = $collection->sortBy(function($item){
return array_search($item->role, ['admin', 'user', 'owner']);
});

View data according to class and class group

I had an admin panel where 3 types of user are there Admin, Teacher and Student. Now I want that when student logged in he/she only see data uploaded by admin
According to his/her class and class group like class=10th and group=computer science. I have no idea how can i get this type of thing. I had used following code
$paper = Paper::where('paper_type','PaperSolution' && 'class',Auth::user()->class)->get();
this is not working properly as I am dumping data
dd($paper);
it is giving me null as answer.
you can use more granular wheres passed as array:
$query->where([
['column_1', '=', 'value_1'],
['column_2', '<>', 'value_2'],
[COLUMN, OPERATOR, VALUE],
...
])
Try this
$paper = Paper::where([['paper_type','PaperSolution'],['class', Auth::user()->class]])->get();
dd($paper);
OR
$paper = Paper::where([['paper_type','=','PaperSolution'],['class','=', Auth::user()->class]])->get();
dd($paper);
Reference for where query using array
ReferenceLink
Please refer to Laravel collection docs to correct syntax.
$paper = Paper::where('paper_type','PaperSolution')
->where('class', Auth::user()->class)
->get();
I did not exactly understand structure of your DB, but at first you need to have corresponding columns to then write any query. Your first option is uploaded by admin so in your uploads table (which is Paper model as I can see from your text) you should have something like uploader_role. Then you have student_class and student_group options. I want to get your attention in fact that this 2 options are users table columns NOT uploads (Paper). So you need to check some permissions of users, then get papers uploaded by admins. You can do that with middleware or just in your controller
$user = Auth::user();
if ($user->class == 10 && $user->group == 'computer_science') {
$papers = Paper::where('uploader_role', 'admin')
// you can add extra where options if that columns exist in papers table and you need to filter them also by class and group
->where( 'class_that_has_permissions', $user->class)
->where( 'group_that_has_permissions', $user->group)
->get();
return $papers;
}
abort(404);
Also be careful with columns that have name class that can return real user class name like App\User, try to use class_name or class_number.

How to groupBy one column and count another column with condition in Laravel?

I have a table for students with column remarks which is equal to pass or fail and a column class to determine their group.
Now I want to get a collection using eloquent that goes like:
Select count(remarks) where 'remarks' equal to pass and
count(remarks) where 'remarks' equal to fail
GROUP BY class
What I have tried so far:
Student::where('remarks', 'pass')
->selectRaw('count(remarks) as passRemark')
->where('remarks', 'fail')
->selectRaw('count(remarks) as failRemark')
->groupBy('class')->get();
The above code doesn't seem to work and it returns nothing, it does work when using 1 where clause which is not what I intend to do and I tried adding another where, the query breaks.
Can anyone suggest the best approach for this?
To keep this in Eloquent, I would use the built in Laravel withCount() method and a closure function for each type of count.
Something like this would be my preference (I have now successfully tested this: each Student will have a count for both):
Student::withCount(['remarks as passRemark' => function ($query) {
$query->where('remarks', 'pass');
}, 'remarks as failRemark' => function ($query) {
$query->where('remarks', 'fail');
}])->groupBy('class')->get();
I guess you should try this query, using DB::raw(), just to see whether it works or not, then you can rewrite using the built in methods from the ORM.
SELECT SUM((CASE WHEN remarks = 'pass' THEN 1 ELSE 0 END)) AS passRemark,
SUM((CASE WHEN remarks = 'fail' THEN 1 ELSE 0 END)) AS failRemark
GROUP BY class

When condition on eloquent with the column values on the table

How can I add in conditional the value of the query i'm using on when function of eloquent laravel?
Here's what I want to happen
$user = User::when('logged' == '3', function ($q){
$q->where('role', 'admin');
)}->get();
As you can see I want to get the role admin only when the column logged is equal to 3 how can I do this one ? thank you.
P.S.
just an example query. thank you.
This is not how when works,
the first condition 'logged' == '3' will always return false;
So it will not use the closure query, directly use get() method, and return all the User's records;
You need to do it like this:
$user = User::where(function($q) {
$q->where(['logged' => 3, 'role' => 'admin'])
})->orWhere('logged', '!=', 3)->get();
You may only want to apply a where statement if a given input value is present on the incoming request. In short you first condition is not base on your table field but base on the request you have. So #TsaiKoga answer's is correct.
The when method only executes the given Closure when the first parameter is true. If the first parameter is false, the Closure will not be executed.
Please read docs here when

Laravel Eloquent and combing data to send to View

I'm trying to figure out a way to combine data from two tables into a single variable that I can then send to my view. I'm using Authority as my authentication bundle and so I have the following tables set up: users, roles, role_user. I want to get the following data into a single variable.
From the users table:
id, name, email
From the roles table:
name
The following returns all the user data in the users table:
$users = User::all();
But, I want to make a chain that can get the related data stored in the roles table? I want all users and all of each users roles together.
And while I can find examples that help get related data for a single record I haven't been able to find any reference to retrieving entire tables with related data.
Thanks.
$users = User::with('roles')->get()
Eager loading is what you are looking for, read the docs :)
Im not 100% sure what you are after, I think you should make relations with Eloquents methods. But if you are looking for a way to just merge the data returned by two models you could do the following:
$users = User::all();
$roles = Roles::all();
$array = array_merge($users->toArray(), $roles->toArray());
return Response::json($array);
You could make the model calls so that they return exactly what you are after and then merge them together. If you want one Model to return something specific just make a function for it.
You need to use something like that:
$user = User::get();
$roles = Roles::get();
$user .= (object) $roles; //because of that both them are object array and we have to combine them as object array...
than you can pass the data to View
return View:make('templatefile')//or Redirect to_route whatever
->with('user', $user);
But the best way is belongs_to in your case. Please read the documentation:
http://laravel.com/docs/database/eloquent#relationships

Resources