Eloquent

Query Builder vs Scopes

  • Use Query Builder for simple queries or one-off queries
  • Use Scopes for reusable queries
  • Use Scopes for complex queries
  • Use Scopes for queries that require multiple conditions

Large Number of Query Scopes

If you have a 3+ query scopes use a query builder object instead.

class User extends Model
{
    #[\Override]
    public function newEloquentBuilder($query): UserEloquentBuilder
    {
        return new UserEloquentBuilder($query);
    }
}

class UserEloquentBuilder extends EloquentBuilder
{
    public function active(): self
    {
        return $this->where('active', true);
    }

    public function hasPosts(): self
    {
        return $this->whereHas('posts');
    }

    public function hasComments(): self
    {
        return $this->whereHas('comments');
    }
}

Reusable Query Scopes

If you have a query scope that is used in multiple models, use a trait.

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

Eager Loading

  • Use Eager Loading to reduce the number of queries and N+1 problems
$users = User::with('posts')->get();

Factories

  • Use factories to generate test data
  • If possible, use states to generate different data
  • Folder structure should match the models
final class UserFactory extends Factory
{
    protected $model = User::class;

    public function definition(): array
    {
        return [
            'name' => $this->faker->name,
            'email' => $this->faker->unique()->safeEmail,
            'password' => Hash::make('password'),
        ];
    }

    public function admin(): self
    {
        return $this->state(function (array $attributes) {
            return [
                'is_admin' => true,
            ];
        });
    }
}
Previous
Home
Next
Jobs