Difference between get() and first() method in laravel [duplicate] - php

What is the difference between these methods:
find()
findOrFail()
first()
firstOrFail()
get()
list()
toArray()
I've been using them and each one gives a different result and sometimes I need to add toArray() at the end of get() because my function is expecting an array. Won't the other methods produce arrays as well?

find($id) takes an id and returns a single model. If no matching model exist, it returns null.
findOrFail($id) takes an id and returns a single model. If no matching model exist, it throws an error1.
first() returns the first record found in the database. If no matching model exist, it returns null.
firstOrFail() returns the first record found in the database. If no matching model exist, it throws an error1.
get() returns a collection of models matching the query.
pluck($column) returns a collection of just the values in the given column. In previous versions of Laravel this method was called lists.
toArray() converts the model/collection into a simple PHP array.
Note: a collection is a beefed up array. It functions similarly to an array, but has a lot of added functionality, as you can see in the docs.
Unfortunately, PHP doesn't let you use a collection object everywhere you can use an array. For example, using a collection in a foreach loop is ok, put passing it to array_map is not. Similarly, if you type-hint an argument as array, PHP won't let you pass it a collection. Starting in PHP 7.1, there is the iterable typehint, which can be used to accept both arrays and collections.
If you ever want to get a plain array from a collection, call its all() method.
1 The error thrown by the findOrFail and firstOrFail methods is a ModelNotFoundException. If you don't catch this exception yourself, Laravel will respond with a 404, which is what you want most of the time.

Probably things changed but the findorFail method can take 2 arguments: $id and $columns mixed/array params respectively. Passing a second arg is not required. That said, this would work:
$post = Post::findOrFail([1,2], ['title', 'subtitle']);
If one of the $ids fails, the ModelNotFoundException with message 'No query results for model ... ' will be thrown.

Related

Laravel - filter collection and then ->toJson, having a minor issue

I have a Laravel controller which takes a search parameter, looks through all the records in a certain time range, uses the laravel collection ->filter method, and then on the results of that filter method, returns the json ->json
$logs = RequestLog::orderBy('created_at', 'DESC')->whereBetween('created_at', [$start, $end])->get();
$logs = $logs->filter(function($log) { /* my own logic in here */ });
return response()->json($logs->toJson());
Now this seems to work just fine. It normally returns an array of the matching records, [{"id":1},{"id":2},{"id":3}]
But if the ->filter function leaves one result, let's say the 25th record in the array, the response now comes out like this: {25: {"id": 25}}. It ruins the normal array structure and returns a JSON object with a single key.
Is this expected? What's up with this? How do I deal with this?
Note: my filter function cannot be done via sql means, it has to be done in PHP.
[edit] it's actually returning an Object JSON anytime the filter results are anything other than the first items in the original Query results.
Normally after applying methods that modifies (especially removes an item from) a collection, the indexes may not come ordered. This is why you need ->values() on the collection.
So you'd have:
return response()->json($logs->values()->toJson());
values() Resets the keys on the underlying array.

Removing rows from a collection changing types of the collection

I have a two collections. First one is a big collection. Another one is remove list. For example:
$data= List::where('status', true)->get();
$list= List::where('begin_at', '<', Carbon::now())->pluck('id');
$result = $data->whereNotIn('id', $list);
This is just a simple example. I have a dynamic data. My question is:
When i return $data, it returns [{}, {}, ...] format
But when i return $result, it returns {}, {}, ...
I tried to $result->toArray(), $result->toCollapse() but none of them is worked.
Why after the get(), using where condition changing the type of the collection? Why array symbols gone? What is the best practices in here to solution? Thanks in advance.
Use all() on the collection to get it as an array with the Eloquent models intact. If you use toArray() instead, it will convert everything to an plain PHP array.
$data->whereNotIn('id', $list)->all();
See docs here
Calling get() on a model will create a collection, and the collection upon creation will call all() on itself. So after modifying the collection you will need to call all() yourself to the the same "format" as from get().

What is the difference between find(), findOrFail(), first(), firstOrFail(), get(), list(), toArray()

What is the difference between these methods:
find()
findOrFail()
first()
firstOrFail()
get()
list()
toArray()
I've been using them and each one gives a different result and sometimes I need to add toArray() at the end of get() because my function is expecting an array. Won't the other methods produce arrays as well?
find($id) takes an id and returns a single model. If no matching model exist, it returns null.
findOrFail($id) takes an id and returns a single model. If no matching model exist, it throws an error1.
first() returns the first record found in the database. If no matching model exist, it returns null.
firstOrFail() returns the first record found in the database. If no matching model exist, it throws an error1.
get() returns a collection of models matching the query.
pluck($column) returns a collection of just the values in the given column. In previous versions of Laravel this method was called lists.
toArray() converts the model/collection into a simple PHP array.
Note: a collection is a beefed up array. It functions similarly to an array, but has a lot of added functionality, as you can see in the docs.
Unfortunately, PHP doesn't let you use a collection object everywhere you can use an array. For example, using a collection in a foreach loop is ok, put passing it to array_map is not. Similarly, if you type-hint an argument as array, PHP won't let you pass it a collection. Starting in PHP 7.1, there is the iterable typehint, which can be used to accept both arrays and collections.
If you ever want to get a plain array from a collection, call its all() method.
1 The error thrown by the findOrFail and firstOrFail methods is a ModelNotFoundException. If you don't catch this exception yourself, Laravel will respond with a 404, which is what you want most of the time.
Probably things changed but the findorFail method can take 2 arguments: $id and $columns mixed/array params respectively. Passing a second arg is not required. That said, this would work:
$post = Post::findOrFail([1,2], ['title', 'subtitle']);
If one of the $ids fails, the ModelNotFoundException with message 'No query results for model ... ' will be thrown.

how to get collection results as array with ids

it should be simple but I am missing something,
lets say this simple eloquent:
Post::select('id')->take(5)->get();
I want to get simple array with the results id's so it will look like this:
[1,2,3,4,5]
but i am getting something like this:
[{"id":"1"},{"id":"2"},{"id":"3"},{"id":"4"},{"id":"5"}]
flatten() not working and I am getting the same results:
Post::select('id')->take(5)->get()->flatten();
http://laravel.com/docs/master/collections#method-flatten
The flatten
method flattens a multi-dimensional collection into a single
dimension:
what i am missing? I remember there is a short line laravel way of getting this results without iterate through the array and create a new one
just got it, its the lists() that do the magic so the answer is:
Post::select('id')->take(5)->lists('id');
Update:
as of laravel 5.2 lists() become deprecated
The lists method on the Collection, query builder and Eloquent query
builder objects has been renamed to pluck. The method signature
remains the same.
the new method name is pluck which work the same:
Post::select('id')->take(5)->pluck('id');

CodeIgniter: Preventing row_array() vs row() typo's?

Twice now I've mistakenly used row() instead of row_array() when fetching a single row result. Usually, it goes unchecked without any warning messages. 15-30 minutes later I finally notice the issue; doh doh!
Does anyone have any good suggestions as to ways to prevent this mistake. The object format doesn't throw a PHP warning, but - of course - the code doesn't work when you expect an array from a model method.
I accidentally used:
if ($query->num_rows() > 0) {
return $query->row();
}
Which should instead be:
if ($query->num_rows() > 0) {
return $query->row_array();
}
I thought about overriding the row() database method and adding in a log_message() statement that would at least let me know (on debug level) that I'm using the object format, instead of the much more typical (for my code) format.
How do you avoid making data-type errors in your CodeIgniter model methods? Simple, declare your methods' return data type.
// returns null or an object
public function getFlatObject(int $id): ?object
{
return $this->db->get_where("your_table", ['id' => $id])->row();
}
// unconditionally returns an array
public function getFlatArray(int $id): array
{
return $this->db->get_where("your_table", ['id' => $id])->row_array();
}
If your return data does not match the declared type(s) (after :), then php is going to generate errors for you.
Let's take this opportunity to clear up any confusion...
If you call either row() or row_array() and your sql logic affords the possibility of more than one row of data -- then you are only going to get the first row of the result set.
If you call row() but there are no rows in the result set, you will have a return value of null.
If you call row_array() but there are no rows in the result set, you will receive an empty array as the return value.
Hence, row() may return an iterable or non-iterable data type; whereas row_array() can ALWAYS be safely passed directly into an iterator (like foreach() or array_map()) -- it just might not having anything to iterate.
row() returns object type, and row_array() returns array.
So it is better in parsing the data of row data in DB when using row_array.
The only way to "prevent" is pretty much learn over the documentation again so you can keep a common habit of using which function.
You can note yourself, if you are going to return multiple records, use the row_array(), for a singular record, use the row() function.
Remember, don't speed type your code, proofread your code step by step before continuing.
Overriding the original function is bad practice, using the row() function is useful when retrieving a singular record, so don't do this.

Categories