Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Custom Model Methods

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?


Edit:

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.

like image 828
Jeremy Harris Avatar asked May 14 '14 15:05

Jeremy Harris


1 Answers

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(); 
like image 98
Laurence Avatar answered Sep 25 '22 23:09

Laurence