BadMethodCallException with message 'Call to undefined method Illuminate\Database\Query\Builder::toArray()' - php

I am working along with #Jeffrey_way series of Laracasts
Many to Many Relations (With Tags)
Below is the code I have written in CMD using Laravel Tinker:
After executing the last line of code ($article->tags()->toArray();
Although everything seems to be OK with my code but still I get following error:
BadMethodCallException with message 'Call to undefined method Illuminate\Database\Query\Builder::toArray()'

If you want to actually "get" relational data, you don't put parenthesis arount tags. This will work just fine:
$article->tags->toArray();
You put parenthesis when you need to "query" to that collection (Ex. sync, save, attach).
Reference: https://laravel.com/docs/5.1/eloquent-relationships#many-to-many

I had the same problem and solved it by adding get()
For example:
$article->tags()->get()->toArray();

Try this instead:
$article->tags()->all()->toArray();
Underlying the tags() is probably a Query\Builder object which represents a query that has not yet run. Instead you need a Collection object which is a query that has run, on which to call toArray(). ->all() is one such call that converts a query builder into a collection by actually running the query.

Related

Laravel Eloquent - Why take(n) works but limit(n) doesn't?

According to laravel docs, take() is just an alias to the limit().
Why doesn't query no 4 doesn't work while other work just fine.
1. $employee->take(2)->get(); // Works
2. $employee->limit(2)->get(); // Works
3. $employee->get()->take(2); // Works
4. $employee->get()->limit(2) // Gives Error; Method Illuminate/Database/Eloquent/Collection::limit does not exist.
When you call get, your database query has been executed, so the result is an Illuminate\Support\Collection and when you call limit on Collection it throws an error because Collection class does not have a limit function.
limit and take are both executed on your database query as they are both functions of Illuminate\Database\Query\Builder and Illuminate\Database\Eloquent\Builder also, not on the Collection.
Notice: the Third statement works because Illuminate\Support\Collection has a take function also.

Eloquent findOrFail()->get()

Bit of a rookie error I know, but can I ask...
Why does
findOrFail()->get();
or
findOrFail()->first();
Return the whole collection, opposed to just failing? The correct syntax I know is just:
findOrFail();
However an accidental ->get() on the end has caused me a nightmare!
The findOrFail($id) method returns a single model by finding through id column and throws an exception - ModelNotFoundException, if model is not found. The get() method return the collection of models/rows.
If you need to find and expect only one model in return by using id, use findOrFail() method only. You dont have to use get() in the end. You can catch the exception and show the respective message in response. Also, you don't have to use first() method in this case, because findOrFail() method will return only one model result.
If you expect a collection of models, use get() method in the end. If there is no result, you'll get an empty collection or array and no exception will be thrown in this case, as the result will be an empty collection/array.
Both findOrFail and firstOrFail throws an exception if the model is not found. This is the default behaviour : https://laravel.com/docs/5.6/eloquent#retrieving-single-models

Laravel update method does not exist

According to the docs, I should be able to update records using update() https://laravel.com/docs/5.4/queries#updates, but I'm getting the error Method update does not exist.
Client::findOrFail($id)->update($request->all());
Any idea why?
I think this is because you are using the query builder's method on a single model object. You cannot do this because the findOrFail method returns a single object that has nothing to do with query builder's methods.
Do it like this: Client::findOrFail($id)->first()->fill($request->all())->save();
Try This:
Client::find($id)->update($request->all());
Or you can use this:
Client::where('id',$id)->first()->update($request->all());

When not or should use get() in Laravel 5

I need to understand when/not to use get(); in Laravel 5.
PHP warning: Missing argument 1 for Illuminate\Support\Collection::get()
Google shows me answers to their issue but no one really explains when you should/not use it.
Example:
App\User::first()->timesheets->where('is_completed', true)->get(); // error
App\Timesheet::where('is_completed', true)->get(); // no error
Fix:
App\User::first()->timesheets()->where('is_completed', true)->get(); // no error
Noticed the timesheets() and not timesheets? Could I have a detail explanation for what is going on, please?
I'm coming from a Ruby background and my code is failing as I do not know when to use () or not.
I'll try to describe this as best I can, this () notation after a property returns an instance of a builder, let's take an example on relationships,
Say you have a User model that has a one-to-many relationship with Posts,
If you did it like this:
$user = App\User::first();
$user->posts();
This here will return a relationship instance because you appended the (), now when should you append the ()? you should do it whenever you want to chain other methods on it, for example:
$user->posts()->where('some query here')->first();
Now I will have a the one item I wanted.
And if I needed say all posts I can do this:
$user->posts;
or this
$user->posts()->latest()->get();
$user->posts()->all()->get();
So the key thing here is, whenever you want to chain methods onto an eloquent query use the (), if you just want to retrieve records or access properties directly on those records then do it like this:
$user->posts->title;
Well, ->timesheet returns a collection, where ->timesheet() returns a builder.
On a Collection you can use ->where(), and ->get('fieldname'), but no ->get().
The ->get() method can be used on a builder though, but this will return a collection based on the builder.
Hope this helps.
The 'problem' you are facing is due to the feature of being able to query relations
When accessing a relation like a property, ->timesheets, the query defined in the relationship is executed and the result (in the form of a Collection) is returned to you.
When accessing it like a method, ->timesheets(), the query builder is returned instead of the resulting collection, allowing you to modify the query if you desire. Since it is then a Builder object, you need to call get() to get the actual result, which is not needed in the first case.
When you use ->timesheets you are accessing a variable, which returns the value of it (in this case an instance of Collection).
When you use ->timesheets() you are invoking whatever is assigned to the variable, which in this case returns an instance of Builder.
whilst pascalvgemert's answer does answer your problem regarding Laravel, it does not explain the difference between accessing or invoking a variable.
In simple term
$user = App\User::get();
is used to fetch multiple data from database
rather
$user = App\User::first();
is used to fetch single record from database

Laravel 5 Using orderBy() with Models

So I can't for the life of me figure out why I can't use orderBy. I'm getting the error:
Call to undefined method Illuminate\Database\Eloquent\Collection::orderBy()
Here is my code:
Route::get('/teams', function(){
$page = 'Teams';
$teams = App\Team::all()->orderBy('teamFirstName')->get();
return view('teams')->with('page', $page)->with('allTeams', $teams);
});
I have tried removing the ->get(); I have tried using just Team::all. I'm using a Laravel cheat sheet and I seem to be following the Model syntax. I have also double checked that it is the right column name in my DB and have even tried using just id.
If I remove the ->orderBy() the query works fine and I can get all of the teams. So what am I doing wrong?
It's because all() returns a Collection which does not have an orderBy method (though it does have a sortBy method which you could use). The following is a bit simpler though and should perform better.
$teams = App\Team::orderBy('teamFirstName')->get();
Once you call all(), the query is ran and results are fetched and any ordering done after this would be done by PHP. It's usually best to let the database handle the ordering though so use orderBy() first before fetching the results with get().
This line:
$teams = App\Team::all()->orderBy('teamFirstName')->get();
Need to be:
$teams = App\Team::orderBy('teamFirstName')->get();
Note:
user3158900 has a good explanation.

Categories