I want to use the different queries inside one method and I want to pass a part of query inside that.
My method looks like this:
static function methodName($partOfQuery)
{
ModelName::where('...')->$partOfQuery->...;
}
And I want to do something like:
$partOfQuery = where('columnName', '>=', 5)->whereRaw('Other Condition');
self::methodName($partOfQuery);
But I was faced with this error:
Call to undefined function App\Classes\ClassName\where()
Anyone could help me with this issue? Thanks
I think that the error is because where is called without an eloquent model class.
Something you can do with query builder is to call a function inside your where condition like:
SomeModel::where(function($query){
// do something
$query->where(...)
})
I doubt there is nothing exactly like what you described. But there are alternatives, if I understand correctly, you are trying to chain multiple methods.
If so, you can do the following:
In your model class:
static function getActiveBooks()
{
return self::where('status', 'active');
}
public function getFeaturedBooks() {
return $this->getActiveBooks()->where('featured', 'active');
}
Usage:
$activeBooks = (new Book())->getFeaturedBooks()->get();
There are multiple ways, you can also use scope as #levi described in the comment section , they are 2 sides of the same coin.
Related
My application supports fetching data with filters. My current implementation (which works fine) is
Model::select($fields)->with($relations)->tap(function ($query) use ($filters) {
// A lot of filtering logic here
// $query->where()......
})->get();
However, I would like to move the filtering logic directly into the Model so I could just do
Model::select($fields)
->with($relations)
->applyFilters($filters)
->get();
I have tried to add a filter method to the Model but at that point I'm working with a Builder and it does not recognize my function:
Call to undefined method Illuminate\Database\Eloquent\Builder::applyFilters()
Is there an easier way to do this, other than creating a new builder class and use that?
I figured it out! I just had to add a scopeApplyFilters to my Model class. It injects the Builder as the first parameter automatically, so the logic ends up looking like
public function scopeApplyFilters($query, $filters)
{
// Perform filtering logic with $query->where(...);
return $query;
}
Then I can just call it with Model::applyFilters($filters);
I'm exactly want to call function into function into class, like how exactly laravel works with oop php
example:
App\Flight::where('active', 1)->orderBy('name', 'desc') ->take(10)->get();
Is that impossible?
Your class methods need to return $this, which will allow you to chain calls like that.
you can call by using $this->functionName();
My Association model looks like this (irrelevant code redacted):
class Association extends Model
{
public function members() {
return $this->hasMany('App\Member');
}
}
My Member model looks like this:
class Member extends Model
{
public function scopeActive($query) {
return $query->where('membership_ended_at', Null);
}
public function scopeInactive($query) {
return $query->whereNotNull('membership_ended_at');
}
}
This is what I want to be able to do:
$association = Association::find(49);
$association->members->active()->count();
Now, I'm aware there's a difference between a Query and a Collection. But what I'm basically asking is if there's some kind of similar scope for collections. Of course, the optimal solution would be to not have to write TWO active methods, but use one for both purposes.
(question already answered in the comments, but might as well write a proper answer)
It is not possible to use a query scope in a Colletion, since query scope is a concept used in Eloquent to add constraints to a database query while Collections are just a collection of things (data, objects, etc).
In your case, what you need to do is to change this line:
$association->members->active()->count();
to:
$association->members()->active()->count();
This works because when we call members as a method, we are getting a QueryBuilder instance, and with that we can start chaining scopes to the query before calling the count method.
am I doing something wrong to be able to access Methods stored in a model in a view. For Example. My User model has a method that looks like
public function isCustomer(){
if (isset($this->customer_id))
return true;
else return false;
}
When I try to access this in the view I end up with Call to a member function getResults() on a non-object.
View code is something like
#if($user->isCustomer)
Something
#endif
Is the model ONLY for database relationships between models or can I store my own class functions here as well?
The function i listed is one of the basic ones. I have quite a few more complicated functions that I would like to run from my User class but am not sure how, as i end up with the same error each time. Should they be stored in the controller?
You can store class functions there. By first glance it looks like your missing () on isCustomer. If it were me I would store that in the controller, like:
$customer = $user->isCustomer();
then pass that to the view.
Here's an example, using Eloquent in Laravel.
Let's say I'm working on a CMS.
the controller takes the route and looks up the page via the route.
the model provides a static function that uses the route to figure out the id of the row it's looking for
the model then uses itself to perform the database query and returns the result
Example Controller Code:
Route::get('(.*)', function($route)
{
$page = Page::load_by_route($route);
});
Example Model Code:
class Page extends Eloquent {
public static function load_by_route($route)
{
// Explode the route and trace to find the actual id of the row we need.
// ... some lines of code to accomplish it...
// Use the $id we discovered to perform the actual query
$page = Page::find($id)->first();
return $page;
}
}
Before you ask "Why can't you just use Page::where('route', '=', $route)->first() in the first place: I'm not wondering 'how to do' this example. I'm just wondering if it is it bad to to be using Page:: inside the page model?
No, but convention says to use self to reference the current class:
$page = self::find($id)->first();