Method orWhere does not exist. Laravel 5.3 - php

BadMethodCallException in Macroable.php line 74:
Method orWhere does not exist.
$category = $categories->where('Node_ID', (explode('.', $cat{$title_id})[0]))
->orWhere('Node_Path', $cat->{$category_name})
->first();
If I try without "orWhere" works, if I use it, throws an Error. Someone knows where is the mistake?

You are trying to use orWhere on collections, thats why its showing you the error. You should use this on model like this (taking Category as a Model):
$category = Category::where('Node_ID', (explode('.', $cat{$title_id})[0]))
->orWhere('Node_Path', $cat->{$category_name})
->first();
See Laravel Docs for orWhere()
Hope this helps!

Related

Call to undefined method Illuminate\Database\Query\Builder::method() error in laravel 5

I am getting an error when i click the delete button which calls Controller#delete method on a controller.
Call to undefined method Illuminate\Database\Query\Builder::destroy()
throw new BadMethodCallException("Call to undefined method
{$className}::{$method}()");
destroy method
public function destroy($id)
{
User::where('role', 'admin')->destroy($id);
return redirect('/home')->with('message', 'Deleted!');
}
::delete() can be used only on Illuminate\Database\Eloquent\Model instance. When you use where() you get Illuminate\Database\Query\Builder. That's the reason why you're getting error. Use ->delete() instead ->destroy() and it will work fine!
First find the record from DB, like:
$user = User::where('role', 'admin')->where('id', $id);
And then delete it, like:
$user->delete();
Hope this will fixed your issue!!
You only can destroy an existing model using key. If you want filters then use delete instead.
laravel docs:
Deleting An Existing Model By Key
User::destroy(1);
User::destroy(array(1, 2, 3));
User::destroy(1, 2, 3);
Of course, you may also run a delete query on a set of models:
$affectedRows = User::where('votes', '>', 100)->delete();

Is it possible to use eager loading with the querybuilder in Laravel?

As one can see above, there is a 'eagerLoad' section and the querybuilder accepts calling $query->with('relation') but produces the following error: Method addEagerConstraints does not exist.
I've tried to find some documentation on this matter but didn't find much. Is it possible at all to use eager loading in this case? If so, could anyone tell how?
Update
As some people pointed out it is possible and the error is caused by another error in my code. Here are some samples:
// Querybuilder
$query->select([
'persons.id as alumni_id',
...
]);
$query->where('...'); // Based on search parameters
$query->groupBy('alumni_id');
$query->with('relation');
$result = collect($query->get());
// Model
public function relation()
{
// Note: relation does have a column person_id
return $this->hasMany(Relation::class, 'person_id', 'alumni_id')->get();
}
Produces
BadMethodCallException in Macroable.php line 81: Method addEagerConstraints does not exist.
As far as I've learned, It is not possible to use eager loading to load Model relations with the querybuilder. (as the querybuilder is not leveraging Eloquent, it doesn't know about the relations)
If anyone knows this to be (partially) incorrect, please let me know.
This should work
// Querybuilder
$query->select([
'persons.id as alumni_id',
...
]);
$query->where('...'); // Based on search parameters
$query->groupBy('alumni_id');
$query->with('relation');
$result = $query->get(); // already returns a collection
// Model
public function relation()
{
// Note: relation does have a column person_id
// A relation should return an Eloquent object (HasMany in this case), not a collection
return $this->hasMany(Relation::class, 'person_id', 'alumni_id');
}

Laravel: Paginate listed users

I have a Laravel aplication, with standard Authentication implemented.
I would like to get the paginated list of the users in a table, but I get this error:
BadMethodCallException in Macroable.php line 81: Method paginate does not exist.
Here is the code:
$users = User::all()->paginate(25);
If I use this without calling the paginate() method, everything works well.
Am I doing something wrong?
I searched a lot, but I cannot find the answer.
Try this code:
$users = User::paginate(25);
The thing is paginate() is kind of doing get() for you. And all() does it too.

Paginate in Laravel

I am writing the below code to paginate record...
$Categories = \App\Models\Skill\Category_Model::all()->paginate(15);
Then I got a runtime error says:
Method paginate does not exist.
Am I missing something ?
You cannot paginate that way, all() function gives you a Collection already.
You need to use \App\Models\Skill\Category_Model::paginate(15) to do that.

Laravel: Get column value from first() result of relationship query

I'm trying to get a single column value from the first result of a Model's belongsToMany relationship query, as i'm returning the ->first() result of the relationship I was hoping $code->reward->title would work but it doesn't.
I get an Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation error
What I'm trying to do is the get the title of the current reward that is linked to a specific code - the code_reward pivot table has a valid_from and expires_at date as the reward linked to a code will change as time goes by, hence the need to get the currently active reward for that code.
Here's my code:
Model: Code
public function rewards()
{
return $this->belongsToMany('App\Reward')->withPivot('valid_from', 'expires_at')->withTimestamps();
}
public function reward()
{
$now = Carbon::now();
return $this->rewards()
->wherePivot('valid_from', '<', $now)
->wherePivot('expires_at', '>', $now)
->first();
}
Controller: CodeController
public function index()
{
$codes = Code::all();
return view('codes/index')->with('codes', $codes);
}
View: Codes/index
#foreach ($codes as $code)
{{$code->id}}
{{$code->reward->title}}
#endforeach
Any help is really appreciated!
Update
Unfortunately both suggestions below ($code->reward()->title and getRewardAttribute() return an Trying to get property of non-object error.
If I remove ->first() from the Code->reward() method and replace $code->reward->title with $code->reward->first() in the view it echoes out the whole reward model as json, however $code->reward->first()->title still returns the Trying to get property of non-object error
Update 2
If I do {{dd($code->reward->title)}} in the view I get the reward title but if I just do {{$code->reward->title}}, I don't!
AND the $code->reward->title works as expected in a #Show view, so could it be that the collection of codes supplied by the controller's #index method isn't passing the necessary data or not passing it in a necessary format??
SOLVED
The issue was caused by one of the $code->rewards in the foreach loop in the index view returning null! The first one didn't, hence the dd() working but as soon as the loop hit a null it crashed.
Once I wiped and refreshed the db (and made sure my seeds where adding only valid data!) it worked. Doing {{$code->reward ? $code->reward->title : ''}} fixed the issue. Grrr.
Your statement is failing because $code->reward->title tells Laravel that you have defined a relationship on your Code model in a method called reward(). However, your relationship is actually defined in the method rewards(). Instead, reward() is a custom method on the model that you have made up. Calling it as a method and not a relation is the quickest way to get what you want.
{{$code->reward()->title}}
As #andrewtweber points out below, you could also make your custom reward() method into an attribute accessor. To do that, just rename the function to getRewardAttribute() and then you can call it in your view like you originally did.
Alternatively, you could get rid of that reward() method entirely and move all of that logic to the controller, where it probably makes more sense. You'd have to use constrained eager loading to pull that off. So in your controller you'd have something like this:
$codes = App\Code::with(['rewards' => function ($query) {
$query->wherePivot('valid_from', '<', $now)
->wherePivot('expires_at', '>', $now);
])->get();
Of course, this would return all of your filtered codes. This is because you cannot apply a sql limit inside a nested eager relationship as outlined here. So in your view, you would then have to do something like this:
{{$code->rewards->first()->title}}
However, it will be simpler to go with my first solution, so that's entirely up to you.
Try to set this method in Code Model, because query builder treats valid_from and expired_at as string, not date?
public function getDates()
{
return ['valid_from','expired_at'];
}

Categories