Refactoring series: Structuring Laravel - Part 1

Every time I start a new Laravel project, I take a little time to decide on how I want to structure it. Since Laravel allows me to organize the folders however I want, I have come up with a couple different approaches to tackle this.

Everything lives in the App namespace

The first approach I have taken was simply to put all files into the App namespace. I placed everything next to the Providers and Console folders. If I needed a place for Jobs or Presenters, I simply created a new folder right in the App namespace. While this is PERFECTLY FINE, it might get a little messy as the project grows.

Please note, I still use THIS kind of structure in most of my apps.

The project contained a lot of classes related to Users, therefore I moved them into App\Users namespace.

For me, it feels a bit weird for the app folder to contain Users folder, which represents domain objects (your models, jobs, etc), along with Providers folder, which provides a “framework-necessary bootstrap” such as RouteServiceProvider.

# The folder structure using the first approach

app
├── Console
│   └── Kernel.php
├── Exceptions
│   └── Handler.php
├── Http
│   ├── Controllers
│   ├── Middleware
│   └── Kernel.php
├── Jobs
│   └── RegisterUser.php
├── Presenters
│   └── ProfilePresenter.php
├── Providers
│   ├── AppServiceProvider.php
│   ├── RouteServiceProvider.php
└── Users
    └── User.php

Domain logic lives in a dedicated folder

To avoid having all classes under the same namespace, I decided to move the domain objects into a dedicated folder. They would all live in a namespace like this: App\Acme.

OK, this solves the problem, doesn’t it? The domain logic and the “framework-necessary bootstrap” are separated.

However, I did not like that my domain logic, the thing that matters the most, is nested inside App\Acme. It makes the impression that code placed in the App namespace, is somehow more important than the domain logic.

# The folder structure using the second approach

app
├── Acme
│   ├── Jobs
│   │   └── RegisterUser.php
│   ├── Presenters
│   │   └── ProfilePresenter.php
│   └── Users
│       └── User.php
├── Console
│   └── Kernel.php
├── Exceptions
│   └── Handler.php
├── Http
│   ├── Controllers
│   ├── Middleware
│   └── Kernel.php
└── Providers
    ├── AppServiceProvider.php
    └── RouteServiceProvider.php

Let’s reverse this.

Support the Support namespace!

The final approach I came up with was to move the “framework-necessary bootstrap” into App\Support namespace. Instead of “hiding” the domain code, I’ll hide the code I do not really want to have.

This enabled me to move every domain related class a level up. Now, the User class is accessible at App\Users\User instead of App\Acme\Users\User!

# The folder structure using the third approach

app
├── Http
│   ├── Controllers
│   └── Middleware
├── Jobs
│   └── RegisterUser.php
├── Presenters
│   └── ProfilePresenter.php
├── Support
│   ├── Console
│   │   └── Kernel.php
│   ├── Exceptions
│   │   └── Handler.php
│   ├── Http
│   │   └── Kernel.php
│   └── Providers
│       ├── AppServiceProvider.php
│       └── RouteServiceProvider.php
└── Users
    └── User.php

Easy right? Well, moving the App\Console\Kernel, App\Http\Kernel or App\Exceptions\Handler classes is not as seamless as moving the domain code. Therefore, I’ll dedicate my next post to a tutorial on how to push the “necessary” code into App\Support namespace.

Feel free to reach out to me on twitter.

© 2020 Jerguš Lejko