Laravel Collection - put specific item on last position - laravel

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']);
});

Related

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.

Select one column with where clause Eloquent

Im using Eloquent. But I'm having trouble understanding Eloquent syntax. I have been searching, and trying this cheat sheet: http://cheats.jesse-obrien.ca, but no luck.
How do i perform this SQL query?
SELECT user_id FROM notes WHERE note_id = 1
Thanks!
If you want a single record then use
Note::where('note_id','1')->first(['user_id']);
and for more than one record use
Note::where('note_id','1')->get(['user_id']);
If 'note_id' is the primary key on your model, you can simply use:
Note::find(1)->user_id
Otherwise, you can use any number of syntaxes:
Note::where('note_id', 1)->first()->user_id;
Note::select('user_id')->where('note_id', 1)->first();
Note::whereNoteId(1)->first();
// or get() will give you multiple results if there are multiple
Also note, in any of these examples, you can also just assign the entire object to a variable and just grab the user_id attribute when needed later.
$note = Note::find(1);
// $user_id = $note->user_id;

Updating a pivot table in Eloquent

I've got a many to many relationship between a student and an institution_contact.
students should only ever have two institution_contacts and I have an attribute on the pivot table named type to be set as 1 or 2.
So, my pivot table looks like this:
institution_contact_student: id, institution_contact_id, student_id, type
I've run into difficulty in deciding how to approach the issue of adding/updating the pivot table. Let's say I have 100 students and I want to assign them a contact with the type of 1.
My current solution is to delete the contact then add it:
$students = Student::all(); // the 100 students
$contactId = InstitutionContact::first()->id; // the contact
foreach ($students as $student) {
// remove existing contact
$student
->institutionContacts()
->newPivotStatement()
->where('type', 1)
->delete();
// add new contact
$student
->institutionContacts()
->attach([$contactId => ['type' => 1]]);
}
However, I'm thinking that this is going to hit the database twice for each student, right? So would I be better off creating a model for the pivot table and removing all entries that matched the student id and the type then simply adding the new ones? Or would creating a model for the pivot table be considered bad practice and is there a better way of accomplishing this that I've missed?
Please note the reason I'm not using sync is because I'm relying on the type attribute to maintain only two contacts per student. I'm not aware of a way to modify an existing pivot without causing issues to my two contacts per student requirement.
Edit:
Instead of creating a model I could run the following code to perform the delete using DB.
DB::table('institution_contact_student') // the pivot table
->whereIn('student_id', $studentIds)
->where('type', 1)
->delete();
If I have understood your question correctly then you can use the updateExistingPivot method for updating your pivot table.But first of course you have to define the pivot in your relationship. For instance,
public function institutionContacts(){
return $this->belongsToMany('institutionContact')->withPivot('type');
}
after this, all you have to do is use the following code:
$student
->institutionContacts()
->updateExistingPivot($contactId, ["type" => 1]);
Hope this helps.

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

Filtering resultset with codeigniter and datamapper

I got a little problem with datamapper, and I'd like to know if there is a quick solution.
Let's say I have this kind of data
Groups table
id | Name
1 | admin
2 | guest
3 | editor
4 | moderator
In my base controller I set a global field to see only the groups that are not admin
$this->groups_ = new Group();
$this->groups_->where('id >', 1)->get();
//so I can select the users that are not admin
$users = new User();
$users->where_related('group',$id,$this->groups_)->get();
Now in my controllers I'd like to filter the groups. For example I want to select only editors and guests (id between 1 and 4). So I would like to filter the initial result set... something like this
$this->groups_->where('id <',4)->get();
But it doesn't work. It returns ALL the group ids < 4 including admin.
What would be the right way to get this?
Well, datamapper does not query objects or groups of objects. It queries the database. So when you do the second get(), you're executing a separate query on the database.
You can do this, but it will be an additional query:
$this->groups_->where('id >', 1)->where('id <', 4)->get();
or you can loop through $this->groups_ after your first query in php and filter the set there and save as an array.
A possible solution
Maybe I found a possible workaround by cloning the datamapper object.
What I want to do is not to query the db multiple times, but I'd like to have a base resultset and refine the results.
So in my base controller I would do something like
$this->groups_ = new Group();
$this->groups_->where('id >', 1);//without getting the results
//so I can select the users that are not admin
$users = new User();
//here i'm getting the results from the clone
$users->where_related('group',$id,$this->groups_->get_clone()->get())->get();
And, as I left the object "open", without getting the results, I can use it in my controllers, as a base for my other "queries"... ok,they are actually new conditions of the first query.
//now the query return the groups between 2, as I set in the base controller
//and 4, set in the child controller
$this->groups_->where('id <',4)->get();

Resources