If you've been working with Laravel—or MVC frameworks in general—for a while, you've likely run into the same issue I have: the Model file becomes huge over time. Just take a look at the illustration below.

From properties like fillable and casts, to scopes, relationships, accessors, mutators, and even custom builders or collections—everything ends up in a single model file. As your project grows, managing such bloated files becomes a pain.

Naturally, we need to split these responsibilities into smaller parts. But how?

This short article suggests a simple strategy: use Traits to organize your model logic more reasonably. (Note: this is not a call to refactor your production code overnight 😃)

The Core Idea

Split common logic into separate Traits and place them under a Concerns folder (a common Laravel convention).

Naming Guidelines:

  • Name your traits based on their function or responsibility.

  • Common trait names include:

    • HasAttributes
    • HasQueryScopes
    • HasRelations
    • ...

This allows:

  • Code reuse across models
  • Easier maintenance
  • Better separation of concerns

Suggested Directory Structure

App/
└── Models/
    ├── User.php
    └── Concerns/
        ├── HasAttributes.php
        ├── HasQueryScopes.php
        └── HasRelations.php

Example: Using Traits in a Model

File: app/Models/Concerns/HasQueryScopes.php

namespace App\Models\Concerns;

trait HasQueryScopes
{
    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    public function scopeSearch($query, $term)
    {
        return $query->where('name', 'like', "%{$term}%");
    }
}

File: app/Models/User.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use App\Models\Concerns\HasQueryScopes;
use App\Models\Concerns\HasAttributes;
use App\Models\Concerns\HasRelations;

class User extends Model
{
    use HasQueryScopes, HasAttributes, HasRelations;

    protected $fillable = ['name', 'email', 'password'];
}

Reusability

If multiple models share the same behavior—like query scopes or relationships—you can simply reuse the traits.

class Post extends Model
{
    use HasQueryScopes, HasRelations;
}

Tip

From now on, if your model requires a new set of related logic (e.g. audit logs, computed attributes...), just create a new trait inside the Concerns folder and apply it.

Conclusion

Organizing your Laravel models using traits is a lightweight, effective, and scalable way to manage growing codebases. It helps make your models more readable and maintainable—especially on large teams or long-term projects.

Happy coding!