Beginners learn Laravel in two ways. One is to obediently fill the program into the MVC framework, resulting in abnormal enlargement of controller and model, which will be difficult to maintain in the future. One is that you often don’t know which class to write your program in, because traditional PHP is a page per file. This article presents a medium to large project architecture that is most suitable for Laravel, easy to maintain, easy to scale, easy to reuse, and easy to test.


Laravel 5.1.24

Controller is too big

Due to RoR, beginners often think of MVC architecture as model, View, controller:

  • A Model is a database.
  • The Controller is responsible for communicating with HTTP, calling model and View.
  • View is HTML.

If you follow this definition, where do these requirements go?

  1. Send Email, use external API.
  2. Logic written in PHP.
  3. Convert the display format as required.
  4. Whether to display certain data on demand.
  5. Display different information as required.

Among them, 1 and 2 belong to business logic, while 3, 4 and 5 belong to display logic. According to the common definition of MVC, model is database, and view is HTML, all the above requirements can not be written in model and View, but only in controller.

Therefore, beginners begin to write a large number of programs in the controller, resulting in the controller is too large to maintain.

Model is too big

When you move logic from Controller to Model, controller gets thinner but Model gets fatter, and model goes from representing databases to being burdened with business logic and display logic, and the results get even worse.

Does Model represent a database? Think of it as the Eloquent Class. The database logic should be stored in repository, which is why Laravel 5 no longer has a Models directory, just the root of the app, Eloquent Class.

Medium to large project architecture

So how do we write that? Don’t limit our thinking to MVC:

  1. Model: Just use it as the Eloquent class.
  2. Repository: Assists the model, handles the database logic, and then injects it into the Service.
  3. Service: Secondary controller, handles business logic, and then injects into controller.
  4. Controller: receives HTTP requests and invokes other services.
  5. Presenter: Handles the display logic and then injects it into the view.
  6. View: Binding data to HTML using blade.

Blue is the original MVC, and purple is the focus of this article: Repository, Service, and Presenter patterns.

The arrow indicates the direction of object dependency injection. 1 1 For details about dependency injection, see Discussing dependency Injection in Depth

We can see that the MVC architecture is still in place due to SOLID’s single responsibility principle and dependency inversion principle:

  1. We separated the database logic from the Model, assisted the Model by repository, and injected the Model dependencies into repository.
  2. We separate the business logic from the Controller, with service assisting the Controller and injecting the Service dependency into the Controller.
  3. We separate the display logic from the View, give presenter assistance to the view, and inject presenter dependencies into the view.

Build directory

inappDirectory creationRepositories.ServicesPresentersDirectory.

Don’t be afraid to create directories other than the Laravel default directory. According to SOLID’s single responsibility principle, the more class features, the more responsibilities, and therefore the more violations of the single responsibility principle, so you should break up your program into smaller parts, each with its own unique functionality. Instead of a single class, you should not have just three MVC parts. Create a directory for your needs and put the appropriate classes in that directory, as long as our class has a namespace to help us classify them.


Due to the lack of space, a separate article will discuss repository. Please refer to how to use the Repository schema.


Due to the lack of space, service will be discussed in a separate article. Please refer to how to Use service Mode.


Due to the lack of space, presenter will be a separate article for discussion. Please refer to how to use Presenter mode?

Unit testing

Because model, View, and Controller dependencies are now separated and use dependency injection, each part can be unit tested separately. Mock repository to test a Service. You can mock other services as well.

A Presenter can also run unit tests alone and mock other services without having to run acceptance tests to test the display logic.


  • The architecture discussed in this article is just the beginning. You can add as many directories and classes as you need. When you find that your MVC is violating the SOLID principles, you can take the class apart and refactor it.

    1. Create a new class or interface.
    2. Inject dependent object dependencies into class.
    3. Handles his responsibilities within class.
    4. Inject a class or interface into a Controller or view.
  • Finally, unit tests are used to test whether the refactored architecture results in the same way as the original requirements.