Symfony 4: How to organize the folder structure (namely, your business logic)

Symfony Best Practices recommends that you do not use packages for organizing business logic.

Bundles should only be used when the code in them is intended to be reused as is in other applications:

But the bundle must be something that can be reused by the autonomous piece of software. If the UserBundle cannot be used "as is" in other Symfony applications, then this should not be its own package.

So, when I upgrade my application from Symfony 3.3 to Symfony 4, I think that this is the right time to reorganize my code.

At the moment, I have been following the "ligament-structure":

- src - AppBundle - Controller - Entity - Repository - Resources - ... - MyNamespace - Bundle - BundleTodo - Controller - Entity - Repository - Resources - ... - BundleCatalog - Controller - Entity - Repository - Resources - ... - BundleCart - Controller - Entity - Repository - Resources - ... - ... 

Now, with the new directory structure, how do I organize the code?

I would like to organize it like this:

 -src - Core - Controller - Entity - Repository - .. - Todos - Controller - Entity - Repository - .. - Catalog - Controller - Entity - Repository - .. - Cart - Controller - Entity - Repository - ... 

But is that right? Are there any problems with the expected folder structure of Symfony 4 and Flex?

Or something better like this:

 -src - Controller - Core - Todos - Catalog - Cart - ... - Entity - Core - Todos - Catalog - Cart - ... - Repository - Core - Todos - Catalog - Cart - ... - ... 

The same applies to other root folders, as described in the project directory structure (how to redefine it).

Are there any rules or restrictions that I should consider when choosing my new folder structure?

THE FIRST SOLVING THE PROBLEM

So, trying to solve the problem, I will go deeper in the documentation, and I will write here what I will find.


+21
symfony symfony4
source share
3 answers

As noted in the comments, Symfony can work well with all of these structures, so really we cannot have an accepted answer here, but here are my two cents.

To be honest, it’s best practice to organize the architecture regardless of the framework (mainly for this reason Symfony 4 no longer imposes a package).

But in reality, with the exception of really specific or complex projects, it will be more practical to have a symfony-oriented organization.

The following are my personal preferences, which are also strongly influenced by the typology of my projects (CRUD-oriented, Rest API, without a strong business logic).

In general, I am moving towards such a structure:

 -src - Controller - Core - Todos - ... - Entity - Core - Todos - ... - Repository - Core - Todos - Validator (or other Symfony oriented components) - Core - Todos - Others (depend on project) - Core - Todos - ... 

Causes:

  • Less service definition with autowire - yes, I'm lazy ;-)

    If you need to register your repositories or controllers as services, you can do this with a single declaration.

  • Symfony Flex recipes typically use this structure.

    The DoctrineBundle, for example, initializes the folders and recipes src/Entity and src/Repository that contain entities, also use this structure.

But remember that Symfony Flex is optional. Its purpose is mainly to facilitate the initiation of the project and make the structure more accessible for beginners.

+7
source share

The 2nd structure is quite suitable for a complex application, business areas are divided.
With Symfony 4, it's easy to customize your application this way.

 β”œβ”€ assets/ β”œβ”€ bin/ β”‚ └─ console β”œβ”€ config/ β”‚ β”œβ”€ doctrine/ β”‚ β”‚ β”œβ”€ core/ β”‚ β”‚ └─ sample/ β”‚ β”œβ”€ packages/ β”‚ β”œβ”€ routes/ β”‚ └─ validator/ β”‚ β”‚ β”œβ”€ core/ β”‚ β”‚ └─ sample/ β”œβ”€ public/ β”‚ └─ index.php β”œβ”€ src/ β”‚ β”œβ”€ Core/ β”‚ β”‚ β”œβ”€ Controller/ β”‚ β”‚ β”œβ”€ Entity/ β”‚ β”‚ β”œβ”€ Repository/ β”‚ β”‚ └─ ... β”‚ β”œβ”€ Sample/ β”‚ └─ ... β”œβ”€ templates/ β”‚ β”œβ”€ core/ β”‚ └─ sample/ β”œβ”€ tests/ β”œβ”€ translations/ β”œβ”€ var/ β”‚ β”œβ”€ cache/ β”‚ β”œβ”€ log/ β”‚ └─ ... └─ vendor/ 

With a little customization: service auto-tuning, auto-configuration, etc. Work like a charm.

 # config/packages/doctrine.yaml doctrine: # ... orm: # ... auto_mapping: true mappings: App\Core: is_bundle: false type: yml dir: '%kernel.project_dir%/config/doctrine/core' prefix: 'App\Core\Entity' alias: 'AppCore' #config/routes/annotations.yaml core_controllers: resource: ../../src/Core/Controller/ type: annotation # config/services.yaml # But I prefer to put this on a separate config/services/_auto.yaml services: App\: resource: '../../src/*/*' exclude: '../../src/*/{Entity,Migrations,Tests,Kernel.php}' app_controller: namespace: App\ resource: '../../src/*/Controller' tags: ['controller.service_arguments'] 
+6
source share

Conway Law:

organizations that develop systems ... are forced to produce projects that are copies of the communication structures of these organizations.

You must develop your directory structure around how you organize your work.

If you or your colleagues work with a full stack for each function, you should group your code for each function. This will facilitate navigation and code detection.

If you or your colleagues are well versed in the server side, interface, translations, etc., you should organize your code around this. The directory structure for each function will maintain a clear division of responsibilities.

In addition, the depth should depend on how large a project you anticipate. If it is 5+ years of work for 5+ people, you probably should go with the division into functions and functions with an attachment, as already mentioned, depending on the organization of work. If this is a three-month project for one person, i.e. some simple internal tool, you probably should use a flatter structure. I would also recommend sticking to the defaults.

In addition, I found this article informative: https://blog.nikolaposa.in.rs/2017/01/16/on-structuring-php-projects/

+5
source share

All Articles