Whenever I add additional logic to Eloquent models, I end up having to make it a static
method (i.e. less than ideal) in order to call it from the model's facade. I've tried searching a lot on how to do this the proper way and pretty much all results talk about creating methods that return portions of a Query Builder interface. I'm trying to figure out how to add methods that can return anything and be called using the model's facade.
For example, lets say I have a model called Car
and want to get them all:
$cars = Car::all();
Great, except for now, let's say I want to sort the result into a multidimensional array by make so my result may look like this:
$cars = array( 'Ford' => array( 'F-150' => '...', 'Escape' => '...', ), 'Honda' => array( 'Accord' => '...', 'Civic' => '...', ), );
Taking that theoretical example, I am tempted to create a method that can be called like:
$cars = Car::getAllSortedByMake();
For a moment, lets forget the terrible method name and the fact that it is tightly coupled to the data structure. If I make a method like this in the model:
public function getAllSortedByMake() { // Process and return resulting array return array('...'); }
And finally call it in my controller, I will get this Exception thrown:
Non-static method Car::getAllSortedByMake() should not be called statically, assuming $this from incompatible context
TL;DR: How can I add custom functionality that makes sense to be in the model without making it a static method and call it using the model's facade?
This is a theoretical example. Perhaps a rephrase of the question would make more sense. Why are certain non-static methods such as all()
or which()
available on the facade of an Eloquent model, but not additional methods added into the model? This means that the __call
magic method is being used, but how can I make it recognize my own functions in the model?
Probably a better example over the "sorting" is if I needed to run an calculation or algorithm on a piece of data:
$validSPG = Chemical::isValidSpecificGravity(-1.43);
To me, it makes sense for something like that to be in the model as it is domain specific.
My question is at more of a fundamental level such as why is all() accessible via the facade?
If you look at the Laravel Core - all() is actually a static function
public static function all($columns = array('*'))
You have two options:
public static function getAllSortedByMake() { return Car::where('....')->get(); }
or
public function scopeGetAllSortedByMake($query) { return $query->where('...')->get(); }
Both will allow you to do
Car::getAllSortedByMake();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With