search
HomeBackend DevelopmentPHP TutorialAnother Way to Structure your Symfony Project

The MVC Services architecture is so common in Symfony projects that it feels like the only way. It’s simple, familiar, and works... until it doesn’t. As your project grows, cracks begin to show: your business logic is everywhere, app behavior is unclear, and maintaining the code becomes painful. While it is the most common approach, Symfony does not force you to stick with it.

What if there was a better way ?


The Frustrations of Using the MVC Services Architecture

 

Domain Logic is Spread Everywhere

As a project grows, business logic tends to spread across the entire code base. Every layer of the project — controllers, services, forms, entities — ends up containing bits and pieces of the domain model. This makes it increasingly difficult to focus on any specific part.

 

The Project Boundaries Are Not Clear

When your architecture is organized around technical layers, it becomes harder to identify clear boundaries between different contexts as the project grows. This lack of clarity can lead to tightly coupled code and maintenance challenges.

Another Way to Structure your Symfony Project

 

The Project Behaviors Are Not Clear

Since the default architecture emphasizes technical layers, it becomes quite challenging to understand the behaviors of the project. You might infer that certain entities are managed by specific services or guess the database schema, but the actual behaviors of the project, which are the most important aspects, remain unclear and implicit.

Another Way to Structure your Symfony Project

 

Different Lifecycles

When business logic is scattered across the project and mixed with implementation details, it becomes difficult to evolve them independently. Over time, The lifecycle of business logic tends to be much longer than that of implementation details (such as frameworks, third-party APIs, or databases). This mismatch forces you to rewrite large portions of code whenever even minor changes occur in a dependency.


A Better Way to Structure Your Architecture

 

Isolate the Business Logic

To make it easier to focus on the business logic when needed, the first step is to isolate it from the rest of the project. To achieve this, create a Domain folder. This folder becomes the core of the project, where business logic is modeled using pure PHP objects, free from dependencies on implementation details. While the rest of the project depends on this folder, the Domain folder depends on no one.

Inside the Domain folder, files should be grouped by domain purpose rather than technical purpose. This means no Entities, Services, or Controllers folders here, only folder names that correspond to features or domain concepts.

Another Way to Structure your Symfony Project

 

The Front Door of the Domain

The most important aspect of a project is what it does, the actions it can handle. These actions represent the project's behaviors and should serve as the only way to access the business logic. To reflect this, create an Application folder that explicitly showcases all the project's behaviors. For example, as a new developer on the project, I should be able to understand at a glance what the project is capable of doing by looking at this folder.

Another Way to Structure your Symfony Project

 

Connecting to the Outside World

With the App and Domain folders, it becomes easy to focus on the business logic. However, at some point, this business logic needs to interact with external systems. To handle this, create a third folder called Infrastructure, which contains all the implementation details such as framework-specific code, database connections, and libraries.

Files in the Infrastructure folder depend on the App and Domain files. For example, they might call an application handler from the App folder or implement an interface defined in the Domain folder.

Another Way to Structure your Symfony Project

Concretely, in Symfony, this involves modifying the Controller folder and declaring which services implement which interfaces.

# config/routes.yaml

controllers:
    resource:
        path: ../src/Catalog/Infrastructure/Controller/
        namespace: App\Catalog\Infrastructure\Controller
    type: attribute

 

Reveal the Boundaries

As your project evolves, you might notice that some parts of the business logic deserve their own space in the architecture. A good indicator is when the same term starts to have different meanings depending on the context. For example, the word Product might refer to a factory product, a warehouse product, or an e-commerce product, each requiring its own model. A god object can also be a good indicator; the User class often has this type of issue in Symfony projects.

When this happens, it’s time to extract it and let its business logic evolve independently.

Some contexts will form the core of your project, while others will support it. Generic contexts, such as Auth, can use a simpler architecture because they are not central to your domain

Another Way to Structure your Symfony Project

In this picture, we can see that the Auth context uses a standard Symfony structure, the Order and Catalog contexts use a domain-focused architecture, and the Shipping context uses a feature-focused architecture.

 

Incremental Modularity

If a specific context grows to the point where it needs to scale independently, consider splitting it into a separate deployment unit.

However, don’t rush into this step. Start by making your project modular, and if you notice that a context needs to scale individually, then deploy it separately.
Only split the codebase if organizational challenges arise, such as two teams struggling to collaborate on the same codebase.

Another Way to Structure your Symfony Project

Go Further
  • Simon Brown - Modular Monoliths

The Concepts

As we explored these solutions, we applied several craftsmanship concepts. Let’s name and briefly explain them, so you can dive deeper into each one.

 

Ubiquitous Language

Behind this unusual term lies a very simple concept. The ubiquitous language is the vocabulary your team uses to describe your domain model. This vocabulary should be documented and consistently used everywhere, in product conversations, the codebase, and beyond.

Concretely, create a markdown file at the root of a Bounded Context and bring together product people, domain experts, and tech teams to define each concept of your project.

Go Further

  • Eric Evans - DDD - Chapter 2 : Communication and the use of language
  • Martin Fowler - Ubiquitous Language

 

Bounded Context

A bounded context defines the linguistic boundary within your project, separating parts of the system where the ubiquitous language no longer aligns. Tools like Context Maps and Event Storming can help identify these boundaries.

A bounded context is an abstract concept; it can be implemented in many ways, from a simple folder in a modular monolith to a cluster in a microservices architecture.

Go Further

  • Eric Evans - DDD - Part IV : Strategic Design
  • Vaughn Vernon - IDDD - Chapter 2 : Domains, Subdomains, and Bounded Context
  • Martin Fowler - Bounded Context

 

Ports and Adapters, Hexagonal, Onion, and Clean Architecture

All these architectures aim to isolate business logic from implementation details. Whether you use Ports and Adapters, Hexagonal, or Clean Architecture, the core idea is to make the business logic framework-agnostic and easy to test.

Once you have this in mind, there is a full spectrum of implementations, and the best one depends on your context and preferences. A major advantage of this architecture is that, by isolating your business logic, it enables much more efficient testing.

Go Further

  • Alistair Cockburn - Hexagonal Architecture
  • Uncle Bob - Clean Architecture
  • Herberto Graca - DDD, Hexagonal, Onion, Clean, CQRS, … How I Put It All Together

 

Screaming Architecture

The idea of organizing folders and files to "scream" the business logic is known as Screaming Architecture. This concept emphasizes that the structure of your code should make the project’s purpose immediately clear. The goal is for a new developer to understand what the project does at a glance.

I highly recommend reading Uncle Bob’s article on the topic—his comparison to a house plan is particularly insightful.

Go Further

  • Uncle Bob - Screaming Architecture

 

Vertical Slicing Architecture

Vertical slicing organizes your project by features, allowing each feature to evolve independently. It enables you to apply different architectures to different features based on complexity and maturity.

Although the idea is interesting, it requires highly skilled engineers to implement and maintain such an architecture effectively.

Go Further

  • Jimmy Bogard - Vertical Slice Architecture
  • CodeOpinion - Vertical Slice Architecture, not Layers!

Final Thoughts

The way you structure your Symfony project has a profound impact on its scalability, maintainability, and clarity. By isolating your business logic and making behaviors explicit, you’ll create a system that’s easier to understand and evolve.

If you’re new to these ideas, don’t worry, software craftsmanship is a journey, not a destination. The concepts might seem overwhelming at first, but each one will help you deliver more value to your business.

Have questions or want to share your experience ? Drop them in the comments ! And stay tuned for the next article ?

The above is the detailed content of Another Way to Structure your Symfony Project. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
What is the difference between unset() and session_destroy()?What is the difference between unset() and session_destroy()?May 04, 2025 am 12:19 AM

Thedifferencebetweenunset()andsession_destroy()isthatunset()clearsspecificsessionvariableswhilekeepingthesessionactive,whereassession_destroy()terminatestheentiresession.1)Useunset()toremovespecificsessionvariableswithoutaffectingthesession'soveralls

What is sticky sessions (session affinity) in the context of load balancing?What is sticky sessions (session affinity) in the context of load balancing?May 04, 2025 am 12:16 AM

Stickysessionsensureuserrequestsareroutedtothesameserverforsessiondataconsistency.1)SessionIdentificationassignsuserstoserversusingcookiesorURLmodifications.2)ConsistentRoutingdirectssubsequentrequeststothesameserver.3)LoadBalancingdistributesnewuser

What are the different session save handlers available in PHP?What are the different session save handlers available in PHP?May 04, 2025 am 12:14 AM

PHPoffersvarioussessionsavehandlers:1)Files:Default,simplebutmaybottleneckonhigh-trafficsites.2)Memcached:High-performance,idealforspeed-criticalapplications.3)Redis:SimilartoMemcached,withaddedpersistence.4)Databases:Offerscontrol,usefulforintegrati

What is a session in PHP, and why are they used?What is a session in PHP, and why are they used?May 04, 2025 am 12:12 AM

Session in PHP is a mechanism for saving user data on the server side to maintain state between multiple requests. Specifically, 1) the session is started by the session_start() function, and data is stored and read through the $_SESSION super global array; 2) the session data is stored in the server's temporary files by default, but can be optimized through database or memory storage; 3) the session can be used to realize user login status tracking and shopping cart management functions; 4) Pay attention to the secure transmission and performance optimization of the session to ensure the security and efficiency of the application.

Explain the lifecycle of a PHP session.Explain the lifecycle of a PHP session.May 04, 2025 am 12:04 AM

PHPsessionsstartwithsession_start(),whichgeneratesauniqueIDandcreatesaserverfile;theypersistacrossrequestsandcanbemanuallyendedwithsession_destroy().1)Sessionsbeginwhensession_start()iscalled,creatingauniqueIDandserverfile.2)Theycontinueasdataisloade

What is the difference between absolute and idle session timeouts?What is the difference between absolute and idle session timeouts?May 03, 2025 am 12:21 AM

Absolute session timeout starts at the time of session creation, while an idle session timeout starts at the time of user's no operation. Absolute session timeout is suitable for scenarios where strict control of the session life cycle is required, such as financial applications; idle session timeout is suitable for applications that want users to keep their session active for a long time, such as social media.

What steps would you take if sessions aren't working on your server?What steps would you take if sessions aren't working on your server?May 03, 2025 am 12:19 AM

The server session failure can be solved through the following steps: 1. Check the server configuration to ensure that the session is set correctly. 2. Verify client cookies, confirm that the browser supports it and send it correctly. 3. Check session storage services, such as Redis, to ensure that they are running normally. 4. Review the application code to ensure the correct session logic. Through these steps, conversation problems can be effectively diagnosed and repaired and user experience can be improved.

What is the significance of the session_start() function?What is the significance of the session_start() function?May 03, 2025 am 12:18 AM

session_start()iscrucialinPHPformanagingusersessions.1)Itinitiatesanewsessionifnoneexists,2)resumesanexistingsession,and3)setsasessioncookieforcontinuityacrossrequests,enablingapplicationslikeuserauthenticationandpersonalizedcontent.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

VSCode Windows 64-bit Download

VSCode Windows 64-bit Download

A free and powerful IDE editor launched by Microsoft

SublimeText3 English version

SublimeText3 English version

Recommended: Win version, supports code prompts!

SublimeText3 Linux new version

SublimeText3 Linux new version

SublimeText3 Linux latest version

MantisBT

MantisBT

Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.