Get last few rows in ascending order in Laravel - laravel

What is the best way (Laravel way) to get last few rows of a database table in ascending order? I want the result to be an array of objects as like:
[{"name1":"value1"}, {"name2":"value2"}]
My recent code is like:
$users = User::take(2)->latest()->get()->reverse();
return $users;
Output looks like:
{"1":{"id":582, "name":"name1"}, "0":{"id":583, "name":"name2"}}
But I want the output to be like:
[{"id":582, "name":"name1"}, {"id":583, "name":"name2"}]

When you use the reverse() method, it modifies the Collection, but doesn't re-index it, meaning the Collection is now [1, 0]. JS/JSON treats this as an Object instead of an array, hence the difference:
{"1":{"id":582, "name":"name1"}, "0":{"id":583, "name":"name2"}}
// VS
[{"id":582, "name":"name1"}, {"id":583, "name":"name2"}]
To solve this, use the values() method to re-index the array before return:
$users = User::take(2)->latest()->get()->reverse();
return $users->values();
// [{"id":582, "name":"name1"}, {"id":583, "name":"name2"}]
If you want them in the other order, don't use reverse(), and you shouldn't need values() either:
$users = User::take(2)->latest()->get();
return $users;
// [{"id":583, "name":"name2"}, {"id":582, "name":"name1"}]

Related

How can i sort a laravel's elequent list by another ids

I have a challenge that if I want to sort the records when getting using Laravel's ORM based on a list of IDs, how should I do it?!!!!!!!
I mean :
Suppose we have a table called users, which contains 100 records and each record has a unique ID.
We also have an array of IDs.
$ids = [4,1,2,3]
Now I want to get the list of users, but only the users who are first in the ids array and secondly according to the same order as they are listed in this array.
User::whereIn('id' , $Ids)->sortBy('id',$ids)->get();
Can you think of a solution to do this?
User::whereIn('id' , $Ids)->sortBy('id',$ids)->get();
The collections sortBy() function can take a custom call back this way:
$users = User::whereIn('id', $Ids)->get()
->sortBy(function($user, $key) use($ids) {
return array_search($user->id, $ids);
});
This will sort your collection according to the given array.
You can also reference the docs for more information.
Note that the sortBy() function must act upon a collection, which means that the get() function must come before it.

How to check if collection's column matches an array

Model CustomerDocuments holds customer docs, doc_id is a column in this model that signifies which document is there.
I have an array of needed document IDs, say $neededDocs = [1,2,3].
How do I check if my collection CustomerDocuments contains $neededDocs in each item of this collection.
if all $neededDocsare present in each CustomerDocuments.doc_id then return true, else, false.
I would like to preform this with collection->contains as follows:
CustomersDocuments::where('customer_id', $customer->id)
->contains('doc_id',$required_onboarding_docs)
->get();
Yet this syntax is wrong
I think you could probably achieve this with something like the following:
$documents = CustomersDocuments::where('customer_id', $customer->id)
->get()
->pluck('doc_id')
->toArray();
The above will output an array with all the doc_id.
return $documents == $neededDocs;
You could then just compare it with your $neededDocs array.
Edit: If you, however, want to check that each row in your collection contains a doc_id that is present in $neededDocs, you could do it like this:
$collection = CustomersDocuments::where('customer_id', $customer->id)->get();
return $collection->contains(function($value, $key) use ($neededDocs) {
return in_array($value->doc_id, $neededDocs);
});
I am not entirely sure which one you want, but these should do the trick.

Sort Collection By id set

I have an array of ids that i want to sort a given column by them in the collection.
For example,
$suppliersOrder = [8,7,5,1,3,4];
$items = Items::get()->sortBy(function($model) use ($suppliersOrder) {
return array_search($model->supplier_id, $suppliersOrder);
})->values();
This acts like ordering items as [1,3,4,5,7,8] instead of the given order. And if I try sortByDesc, likewise [8,7,5,4,3,1] but I couldn't figure out the way to actually sort them as my given array's order.
My ultimate goal is then running $items->groupBy('supplier.name') so I can have my desired order.
What Alexander Villalobos suggested in the comments, I changed my code like this:
$items = Items::get()->sortBy(function($model) use ($suppliersOrder) {
return rsort($model->supplier_id, $suppliersOrder);
});
Indirect modification of overloaded property App\Item::$supplier_id has no effect
$suppliersOrder = [8,7,5,1,3,4];
$items = Items::get()->sortBy(function($row,$key) use ($suppliersOrder) {
return array_search($row->supplier_id, $suppliersOrder);
});
This should give you sorted collection of items by the order you described in $suppliersOrder. As per Laravel docs, the parameters to the callback function include one being the row for the collection and another being the key of that row in the collection.

Laravel Eloquent ORM - How to get the all the properties of afrom/of a collection in a array?

$user_emails = ["email_1#domain.com", "email_2#domain.org"];
$users = Users::whereIn("email", $user_emails);
The table for users also has a phone column for each user. What's the best way to get a list/array of the phone number as an array?
$users->all()->phone(); // Like (which is not correct)
Try to use get() like :
$users = Users::whereIn("email", $user_emails)->get(['phone'])->toArray();
Or also pluck() like :
$users = Users::whereIn("email", $user_emails)->pluck('phone')->all();
Hope this helps.
Use pluck method to fetch a specific column's values and then use toArray on returned Collection object to get results as an array.
$phoneNumbers = Users::whereIn("email", $user_emails)->pluck('phone')->toArray();
You can get all column data with get()
Example:
$user = $user::where('email', $user_emails)->get();
You can get the list with foreach loop method.

laravel database query Does `where` always need `first()`?

I am new to laravel and confused about some query methods.
find($id) is useful and returns a nice array, but sometimes I need to select by other fields rather than id.
The Laravel document said I could use where('field', '=', 'value') and return a bunch of data, which is fine.
What I can't understand is why I need to add ->first() every time, even if I am pretty sure there is only one single row matches the query.
It goes like this:
$query->where(..)->orderBy(..)->limit(..) etc.
// you can chain the methods as you like, and finally you need one of:
->get($columns); // returns Eloquent Collection of Models or array of stdObjects
->first($columns); // returns single row (Eloquent Model or stdClass)
->find($id); // returns single row (Eloquent Model or stdClass)
->find($ids); // returns Eloquent Collection
// those are examples, there are many more like firstOrFail, findMany etc, check the api
$columns is an array of fields to retrieve, default array('*')
$id is a single primary key value
$ids is an array of PKs, this works in find method only for Eloquent Builder
// or aggregate functions:
->count()
->avg()
->aggregate()
// just examples here too
So the method depends on what you want to retrieve (array/collection or single object)
Also the return objects depend on the builder you are using (Eloquent Builder or Query Builder):
User::get(); // Eloquent Colleciton
DB::table('users')->get(); // array of stdObjects
even if I am pretty sure there is only one single row matches the query.
Well Laravel cant read your mind - so you need to tell it what you want to do.
You can do either
User::where('field', '=', 'value')->get()
Which will return all objects that match that search. Sometimes it might be one, but sometimes it might be 2 or 3...
If you are sure there is only one (or you only want the first) you can do
User::where('field', '=', 'value')->first()
get() returns an array of objects (multiple rows)
while
first() returns a single object (a row)
You can of course use get() when you know it will return only one row, but you need to keep that in mind when addressing the result:
using get()
$rez = \DB::table('table')->where('sec_id','=','5')->get();
//will return one row in an array with one item, but will be addressed as:
$myfieldvalue = $rez[0]->fieldname;
using first()
$rez = \DB::table('table')->where('sec_id','=','5')->first();
// will also return one row but without the array, so
$myfieldvalue = $rez->fieldname;
So it depends on how you want to access the result of the query: as an object or as an array, and also depends on what "you know" the query will return.
first() is the equivalent of LIMIT 1 at the end of your SELECT statement. Even if your query would return multiple rows, if you use first() it will only return the first row

Resources