Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practices for large models in Laravel

I have decided to recreate an existing site I have in Laravel as a means of learning how the framework works and have come across a problem I cannot seem to get a decent explanation for.

I currently use a custom MVC framework I built. At the moment I will have a "model" that has a lot of business logic in it. So for example, in my UserModel I have all the functions that interact with the database but I also have many other functions that are User related but has no interaction with the database.

Is it okay to put this code in an Eloquent model?

like image 272
Martin Currah Avatar asked Mar 08 '16 12:03

Martin Currah


People also ask

Is Laravel good for large applications?

Perfect for large-scale solutions This whole package helps to build everything from scratch, be it simple websites or even large-scale applications. You have to check out the various reasons why you should choose Laravel Framework for large-scale applications.

Why we use fillable in Model in Laravel?

In eloquent ORM, $fillable attribute is an array containing all those fields of table which can be filled using mass-assignment. Mass assignment refers to sending an array to the model to directly create a new record in Database.

Does Laravel have many through relations?

The “has-many-through” relationship provides a convenient shortcut for accessing distant relations via an intermediate relation. The first argument passed to the hasManyThrough function is the name of the final model we wish to access, while the second argument is the name of the intermediate model.


3 Answers

It's ok. But if the model class is becoming too big, sometimes i create a 'manager' object to push away some responsability out of the model class. For example:

class User extends Model
{
    protected $permissionManager;

    public function __contruct(){

        //create a Manager object (in laravel create it through App:make )
        $this->permissionManager = new PermissionManager( $this );
    }
}

class PermissionManager
{
    protected $user;

    public function __contruct(User $user){
        $this->user = $user;
    }

    public function hasAccessTo(Resource $res){
        //code
    }

    public function isManager(){
        //code
    }
}

These manager objects are strictly related with the user model, in fact you pass the dependency of the model to the constructor of the manager class, but the primary benefit is that you avoid to create 'god' classes and keep the responsabilities diveded using object composition.

With this structure you can call:

$user->permissionManager->hasAccessTo( $resource );

You can even use interfaces, subclass you User and PermissionManager classes, and create different types in your hierarchies depending on the instance (aka factory method)

Another way to lighten your models is to use Traits. Laravel itself uses traits in various parts of the app; take a look at the core classes to see how they're used. For various reasons many people don't like traits very much, the advantage of the approach i've just proposed is that it's more explicit over using traits and less prone to conflicts

like image 149
Moppo Avatar answered Oct 10 '22 11:10

Moppo


There are few opinions, but I think it's ok to keep User related logic there. At least I saw exactly the same approach in really big projects, where are a lot of bloated Controller/Model classes. Using single responsibility principle is a good idea, but do not be fanatic when you use it. Overengineering is evil.

like image 36
Alexey Mezenin Avatar answered Oct 10 '22 12:10

Alexey Mezenin


I would suggest you utilize traits. You can have a traits folder inside your app directory. I would then categorize each function in its separate folder like:

  • The functions using database will be in app/traits/database folder.
  • The functions not using database will be in app/traits/misc folder.

I would then create an abstract class called UserFunctions.phpwhich will include all the traits. Then i will just extend my User model with the abstract class.

class User extends BaseUser,UserFunctions   
like image 28
Raza Mehdi Avatar answered Oct 10 '22 10:10

Raza Mehdi