Originally published on laravel.learnio.dev — part of the Laravel best practices course. View this lesson on the original site.

In this lesson

Laravel philosophy is about shipping maintainable features quickly, with conventions that reduce repeated decisions.

The core idea: sensible defaults first

Laravel is opinionated in useful ways:

  • predictable folders and naming,
  • strong defaults for routing, validation, and data access,
  • clear extension points when you need custom behaviour.

You start with conventions, then customise only where your app needs it.

flowchart LR
  A[Laravel conventions] --> B[Faster first implementation]
  B --> C[Consistent team code]
  C --> D[Easier maintenance]

Convention over configuration in practice

A lot works with little setup:

  • controllers go in app/Http/Controllers,
  • Blade views go in resources/views,
  • migrations go in database/migrations,
  • type-hinted dependencies are auto-resolved by the container in many cases.

This is why a new team member can usually navigate a Laravel codebase quickly.

Developer experience matters

Laravel treats developer productivity as a feature:

  • expressive APIs (Route, Validator, Mail, Queue),
  • first-party tools (artisan, migrations, testing support),
  • documentation that is versioned and practical.

The aim is readable code that teams can extend safely.

Pragmatism over purity

Laravel is not trying to win architecture debates. It is designed to help you deliver working software:

  • use Eloquent when it helps,
  • drop to Query Builder or raw SQL when needed,
  • keep business logic in sensible boundaries (controllers, services, actions).

You are encouraged to choose what is clear and reliable, not what is fashionable.

Progressive adoption is intentional

You can start simple and scale up:

  • route closures to controllers,
  • basic controllers to form requests and services,
  • sync work to queues and jobs,
  • local logs to full observability tooling.

This means you do not need a "perfect architecture" on day one to build correctly.

Limitations as projects grow

As a codebase gets larger, default Laravel patterns can become stretched if everything stays in controllers and models:

  • fat controllers that coordinate too much,
  • model classes carrying unrelated business rules,
  • cross-feature coupling that makes changes risky.

This is usually an architecture discipline issue, not a Laravel failure.

Where DDD can be a better fit

For complex domains, Domain-Driven Design can give clearer boundaries:

  • domain concepts modelled explicitly,
  • use-case focused application services,
  • infrastructure details isolated from domain rules.

DDD is often better when business rules are deep, change often, or must be highly explicit.

Laravel still supports a DDD direction

You can evolve into DDD while keeping Laravel strengths:

  • keep Laravel at the edges (HTTP, queues, console, persistence),
  • move domain logic into dedicated domain and application layers,
  • use the container to wire interfaces to implementations,
  • use Eloquent as a persistence tool, not your whole domain model.

Old way:

flowchart TB
  A[app/] --> B[Http/Controllers/]
  A --> C[Models/]

  B --> B1[OrderController.php]
  B --> B2[ProductController.php]

  C --> C1[Order.php]
  C --> C2[Product.php]

  B1 --> C1
  B2 --> C2

  C1 --> D[(Database)]
  C2 --> D

DDD direction in Laravel:

flowchart TB
  A[app/] --> B[Http/Controllers/]
  A --> C[Domain/]
  A --> D[Application/]

  B --> B1[OrderController.php]
  B --> B2[ProductController.php]

  C --> C1[Order/]
  C --> C2[Product/]

  C1 --> C1a[Order.php]
  C1 --> C1b[OrderService.php]
  C1 --> C1c[OrderRepository.php]

  C2 --> C2a[Product.php]
  C2 --> C2b[ProductService.php]
  C2 --> C2c[ProductRepository.php]

  D --> D1[PlaceOrderAction.php]
  D --> D2[UpdateProductAction.php]

Laravel does not force an anemic or "all logic in controllers" style. It gives you a productive default, then enough flexibility to adopt stricter architecture when your project needs it.

A decision check you can use today

When choosing an approach in Laravel, ask:

  1. does it follow framework conventions,
  2. will another developer understand it quickly,
  3. is it easy to test and change later?

If the answer is yes, you are usually aligned with Laravel philosophy.

From Laravel best practices — What is Laravel?