when to use get() in query laravel 5 - laravel

I have a basic query set up in the show method of a laravel resource
public function show($id){
$results = Student::find($id);
$drives= Drive:: where('student_id', $id);
}
The query for $results works perfectly. The query for $drives does not work unless I do ->get() at the end of it. Why is this? what's the difference between the two queries so that one requires the ->get() and the other does not? Solving this problem took me like 5 hrs and i'm just curious as to the functionality behind it so i can avoid this headache in the future.

Some eloquent expressions have a get implicitly. Those ones who are made by a Query Builder will need a ->get() call, find(), findOne()... won't need a get().
https://laravel.com/docs/5.6/eloquent#retrieving-models
https://laravel.com/docs/5.6/queries

use get to execute a builder query. unless you run the get() query wont be executed. get will return a collection.
1 - Use query builder to build queries however you want.
$drives= Drive:: where('student_id', $id);
dd($drives); // will return a query builder, you can use it to build query by chaining
2 - when you are ready to execute the query call get()
$drives= Drive:: where('student_id', $id);
$result = $drives->get()
dd($result); // will return a database query result set as a collection object
If you want to get a single object by id use find, to get a single object
$results = Student::find($id);
dd($result); will return a single model

Using the function find() on a model gets a query result based on the primary key of the model, id in this case.
When using where(), it gets a collection (an object of all query results), so if you only want the first result you must call $drives=Drive::where('student_id', $id)->first();
Here is a more in-depth explanation: the difference of find and get in Eloquent

Related

Method Illuminate\Database\Eloquent\Collection::orderby does not exist

$posts = Post::all()->orderby('created_at','desc')->where('usr_id','=',session('LoggedUser'))->get();
return view('admin.profile',compact('userInfo' , 'posts'));
i am making a custom auth for a journal activity but i cant sort the content i shows this error
"Method Illuminate\Database\Eloquent\Collection::orderby does not exist. "
$posts = Post::where('usr_id','=',session('LoggedUser'))->orderby('created_at','desc')->get();
True query like that. When you take all() already query done.
Change it to:
$posts = Post::where('usr_id','=',session('LoggedUser'))->orderby('created_at','desc')->get();
you cant use all() and orderBy because all() does not allow the modification of the query.
I believe this might be because you typed orderby instead of orderBy (notice the uppercase). See laravel orderBy documentation if needed.
Plus, as mentionned by other, don't use all() if you need to do other thing (where clause, order by, etc) in you query.
Change the orderby to orderBy. This could be the reason you are getting the error.
$posts = Post::all()->orderBy('created_at', 'DESC')->where('usr_id','=',session('LoggedUser'))->get();
return view('admin.profile',compact('userInfo' , 'posts'));
Or...
If you want to get specific number of posts you can do it this way to avoid using the Post::all
$posts = Post::orderBy('created_at', 'DESC')->where('usr_id','=',session('LoggedUser'))->paginate(5);
return view('admin.profile',compact('userInfo' , 'posts'));
Yeah this is pretty confusing and just got me as well.
The actual problem isn't the capitilization typo (orderby versus orderBy) but rather the fact that you're using ->all() instead of just Model::orderBy()->...
The moment you use ->all() the object is transformed to another type of collection object and the normal methods one would expect do not exist.
In this case you should rather use sortBy().
See here.

Remove Limit From Eloquent Query

How can I remove the limit/offset from the below query?
$query = TestModel::where('a', 'b')->limit(100);
$query->removeLimit();
I'm using a query from another module and I don't want to change the code.
You can reset the $limit property:
$query = TestModel::where('a', 'b')->limit(100);
$query->limit = null;
$unlimited = $query->get();
$query->getQuery()->limit = null;
One can reset the limit by passing the null value to the limit method.
$query->limit(null);
Works both with Eloquent\Builder and Query\Builder.
The simple answer to your question is - you cannot. Because you have already filtered the result set to a limit of 100 tuples.
What is the reason for you to avoid the change in code in the Model? Because what #Dhruv has suggested is the correct way to achieve what you want to.
In fact, if you still want to keep the code intact. You can rather define another function in your model this way and use it internally in your old function:
public function newFunction(){
return TestModel::where('a', 'b')->get();
}
public function oldFunction(){
return $this->newFunction()->limit(100);
}
Keeping your code consistent, then use newFunction() in your Controller to do whatever you want to.
get(): To get all record from table use get():
$query = TestModel::where('a', 'b')->get();
limit(): To limit the number of results returned from the query
$query = TestModel::where('a', 'b')->limit(10)->get();

Laravel Eloquent: count($result) vs $result->count()

I'm a bit new to this, and was originally trying to check if my model was returning results with isEmpty(), but thought I'd try count() instead, then I came across the following:
I've got the following code, which returns data from my model:
$results = Game::where('code', '=', $code)->with('genre', 'creator')
And whether I use first() or get() combined with count(result) or $results->count() I get different values, and I'm not sure why.
when using ->first()
dd($results->count()) = 11930 // Number of rows in the db
when using ->get()
dd($results->count()) = 1 // What I'd expect the query to return
when using ->first()
dd(count($results)) = "count(): Parameter must be an array or an object that implements Countable"
when using ->get()
dd(count($results)) = 1
I don't understand 1) why when using first, the count is the same as every row in the db. 2) Why count() can't be used with first().
Is anyone able to shed some light as to why I can't use count on first as I'd like to?
Update:
I'm also not able to use ->isEmpty() with ->first() but can with ->get()...?
When I try using it with first, I get Illuminate\Database\Query\Builder::isEmpty does not exist.
Disclaimer: I'm not sure why your database count and your results count aren't the same, however I can shed some light on the different types of count.
Game::where('code', '=', $code)->count();
This is being called on a query builder instance. It is run on the database query, without selecting all the rows. Check out the title Aggregates here: https://laravel.com/docs/5.7/queries
Game::where('code', '=', $code)->get()->count();
As soon as your use get() laravel selects the rows, boots them all as models, and creates a collection. This count is on the collection (a bit like an array) so just gets the number that are returned (i.e. if they are paginated or anything like that it will just get that amount). Check out Count here.
Game::where('code', '=', $code)->first()->count();
This is being run on the first returned model... unless you've written it, a default laravel model won't have a count() method.
count($results)
Finally, count() when not a class method is just the default php function that returns the length of an array or other object (documentation).
First of all,
get() returns collection of objects while first() returns modal object of query.
$results = Game::where('code', '=', $code)->with('genre', 'creator')
dd($results->count()) = 11930 // Number of rows in the db
when using ->get()
$results = Game::where('code', '=', $code)->with('genre', 'creator')->get()
dd($results->count()) = 1
because it has collection, which contains numbers of objects of database data. As ->count getting only one collection so it returns 1.

Eager load single item with Eloquent belongsToMany

I have a Batch model, which hasMany Results and belongsTo a Project. The current status of a batch is based on the status of its most recent Result. So, in my batch model I have this:
public function allForProject($pid)
{
$batches = $this
->with(static::$relatedObjects)
->with('current_status')
->where('project_id', '=', $pid)
->get();
return $batches;
}
public function current_status()
{
return $this
->belongsToMany('BehatEditor\Models\Result')
->orderBy('created_at', 'DESC')
->limit(1)
;
}
...So by saying "->with('current_status')" I am trying to eager load only the most recent result for that batch - there may be thousands of them per batch that I do not want to return to the front end.
Now, this doesn't break, but the "limit(1)" actually seems to limit the number of Batches that get returned with a Result. Even though each one of my Batches has 2 results with my test data, when I use limit(1) only one of them comes back with any data. When I use limit(2), only 2 batches come back with a single current_status record (desired) but the rest have an empty array for current_status.
This is a Silex project using Eloquent as an ORM, so Laravel specific methods won't work.
Any help is much appreciated!
UPDATE:
It looks like Eloquent just doesn't support this. see http://irclogs.julien-c.fr/2013-12-19/01:48#log-52b25061a599aafb54008650. I would like to update my question to be how can I cleanly add the raw SQL I need to my query? Can I supply my own method that holds only the SQL needed, or do I need to replace all ORM usage in allForProject()?
Instead of ->limit(1), use ->first().
Update: Misread what you said, this should work.

Laravel - When to use ->get()

I'm confused as to when ->get() in Laravel...
E.G. DB::table('users')->find(1) doesn't need ->get() to retrieve the results, neither does User::find(1)
The laravel docs say "...execute the query using the get or first method..."
I've read the Fluent Query Builder and Eloquent docs but don't understand when the usage of get() is required...
Thanks for the help
Since the find() function will always use the primary key for the table, the need for get() is not necessary. Because you can't narrow your selection down and that's why it will always just try to get that record and return it.
But when you're using the Fluent Query Builder you can nest conditions as such:
$userQuery = DB::table('users');
$userQuery->where('email', '=', 'foo#bar.com');
$userQuery->or_where('email', '=', 'bar#foo.com');
This allows you to add conditions throughout your code until you actually want to fetch them, and then you would call the get() function.
// Done with building the query
$users = $userQuery->get();
For find(n), you retrieve a row based on the primary key which is 'n'.
For first(), you retrieve the first row among all rows that fit the where clauses.
For get(), you retrieve all the rows that fit the where clauses. (Please note that loops are required to access all the rows or you will get some errors).
find returns one row from the database and represent it as a fluent / eloquent object. e.g. SELECT * FROM users WHERE id = 3 is equivalent to DB::table('users')->find(3);
get returns an array of objects. e.g. SELECT * FROM users WHERE created_at > '2014-10-12' is equivalent to DB::table('users')->where('created_at', '>', '2014-10-12')->get() will return an array of objects containing users where the created at field is newer than 4014-10-12.
The get() method will give you all the values from the database that meet your parameters where as first() gets you just the first result. You use find() and findOrFail() when you are searching for a key. This is how I use them:
When I want all data from a table I use the all() method
Model::all();
When I want to find by the primary key:
Model::find(1)->first();
Or
Model::findOrFail(1)->first();
This will work if there is a row with a primary key of one. It should only retrieve one row so I use first() instead of get(). Remember if you deleted the row that used key 1, or don't have data in your table, your find(1) will fail.
When I am looking for specific data as in a where clause:
Model::where('field', '=', 'value')->get();
When I want only the first value of the data in the where clause.
Model::where('field', '=', 'value')->first();
Basically what you need to understand is that get() return a collection(note that one object can be in the collection but it still a collection) why first() returns the first object from the result of the query(that is it returns an object)
#Take_away
Get() return a collection first() return an object
You can use get() method with latest() method to get the latest record that were recently added to your table
For example
$user=Student::latest()->get();
return all the data in descending order

Resources