15
votes

The release of the popular framework's 4th version was marked by a capital changes in the structure for projects. Including the official documentation notes the following regarding the code bundling (http://symfony.com/doc/current/bundles.html):

In Symfony versions prior to 4.0, it was recommended to organize your own application code using bundles. This is no longer recommended and bundles should only be used to share code and features between multiple applications.

In the 2nd and 3rd versions, the bundle performed two main tasks. 1) If the developer or a group of developers in their different projects used one large repetitive functional, then it could be taken out in a separate bundle and transferred from the project to the project. A good example of such use is a system of users in any project. It includes the models of User, Role, Permission (and possibly others), controllers for entity, plus controllers for signing in the app, signing out the app (the security policy may be different at the same time), and templates for view. Another good example is the administrative panel, the foundation for which is identical. 2) Symfony took separate functionality in different directories from the logic point of view and, accordingly, namespaces by bundling. For example, on one of my past projects, I divided the spaces: user management system, application gamification (social network goal), partner space, geo-environment (for working with maps and defining cities by IP), an environment for payment transactions. As follows. Symfony[2-3] project structure

In my next project I do not want to use anything other than Symfony4 to follow the best practices of the framework during the implementation of its new features. How can I organize the separation of logically independent code in different areas, if the official documentation no longer insists on the creation of bundles??? If all the classes of the model are stored in the same directory, this creates confusion and increases the time to find the desired file in the structure of a large project. The same applies to templates and indeed everything else. When I work with one functional, I have only dropdowned directories of this functionality.

Is it now that Symfony encourages you to define the structure of classes, templates and the like at your own discretion?

4

4 Answers

8
votes

Being new to Symfony and starting with Version 4.2, I had the same problem as @DeveloperMobile.

Directory Structure

This is my Directory Structure based on the recommendations from the Guide Symfony Best Practices Version 4.2

The recommendation basically says about the structure:

  • Put all Controllers in /src/Controller, divided by Subfolder
  • Dont use Bundles, organize your Code by Namespaces
  • Put assets, config, tests, templates, translations, var/cache and var/log in the Root Folder
  • Organize your Business Logic in /src
  • Use autowiring to automate the configuration of application services.
  • Use dependency injection to fetch services
  • Thin controllers and fat model

So basically it says: Yes, you can organize your Code in /src with Subfolders, but Code with a Certain Functionality, like Controller, Entity, Form, Repository, etc. should be in the specific Directory.

Implementation

root/
├─ assets/
├─ bin/
│  └─ console
├─ config/
└─ public/
│  └─ index.php
├─ src/
   ├─ Controller/
     ├─ DefaultController.php
     ├─ ...
     ├─ Api/
     │   ├─ ..
     │   └─ ..
     ├─ Backend/
     │   ├─ ..
     │   └─ ..
   ├─ Entity/
   ├─ Form/
   ├─ Repository/
   ├─ Twig/
   ├─ Utils/
   └─ Kernel.php
├─ tests/
├─ templates/
├─ translations/
├─ var/
│  ├─ cache/
│  └─ log/
└─ vendor/

Best Practice Symfony 4.2

This is the List of all recommendations from the Link above:

Installation

  • Use Composer and Symfony Flex to create and manage Symfony applications.
  • Use the Symfony Skeleton to create new Symfony-based projects.

Structure

  • Don't create any bundle to organize your application logic.

    (Symfony applications can still use third-party bundles (installed in vendor/ ) to add features, but you should use PHP namespaces instead of bundles to organize your own code.)

Configuration

  • Define the infrastructure-related configuration options as environment variables. During development, use the .env and .env.local files at the root of your project to set these.

  • Define all your application's env vars in the .env file

  • Define the application behavior related configuration options in the config/services.yaml file.
  • Use constants to define configuration options that rarely change.
  • The name of your configuration parameters should be as short as possible and should include a common prefix for the entire application.

Business Logic

For most projects, you should store all your code inside the src/ directory. Inside here, you can create whatever directories you want to organize things:

  • Use autowiring to automate the configuration of application services.
  • The id of your application's services should be equal to their class name, except when you have multiple services configured for the same class (in that case, use a snake case id).
  • Services should be private whenever possible. This will prevent you from accessing that service via $container->get() . Instead, you will need to use dependency injection.
  • Use the YAML format to configure your own services.
  • Use annotations to define the mapping information of the Doctrine entities.

Controllers

  • Make your controller extend the AbstractController base controller provided by Symfony and use annotations to configure routing, caching and security whenever possible.
  • Don't add the Action suffix to the methods of the controller actions.
  • Don't use the @Template annotation to configure the template used by the controller. -Don't use $this->get() or $this->container->get() to fetch services from the container. Instead, use dependency injection.
  • Use the ParamConverter trick to automatically query for Doctrine entities when it's simple and convenient.

Templates

  • Use Twig templating format for your templates.
  • Store the application templates in the templates/ directory at the root of your project.
  • Use lowercased snake_case for directory and template names.
  • Use a prefixed underscore for partial templates in template names.
  • Define your Twig extensions in the src/Twig/ directory. Your application will automatically detect them and configure them.

Forms

  • Define your forms as PHP classes.
  • Put the form type classes in the App\Form namespace, unless you use other custom form classes like data transformers.
  • Add buttons in the templates, not in the form classes or the controllers.
  • Do not define your validation constraints in the form but on the object the form is mapped to.

Internationalization

  • Store the translation files in the translations/ directory at the root of your project.
  • Use the XLIFF format for your translation files.
  • Always use keys for translations instead of content strings.

Security

  • Unless you have two legitimately different authentication systems and users (e.g. form login for the main site and a token system for your API only), we recommend having only one firewall entry with the anonymous key enabled.
  • Use the bcrypt encoder for hashing your users' passwords.
  • Define a custom security voter to implement fine-grained restrictions.

Web Assets

  • Store your assets in the assets/ directory at the root of your project.
  • Use Webpack Encore to compile, combine and minimize web assets.

Tests

  • Define a functional test that at least checks if your application pages are successfully loading.
  • Hardcode the URLs used in the functional tests instead of using the URL generator.
2
votes

As they say(source), you define your own structure, it's not recommended to refactor all your actual application

Our recommendation is sound and clear: you may use these best practices for new applications but you should not refactor your existing applications to comply with these best practices.

I hope you got you're answer :)

0
votes

As @Nelson said, no need to refactor your current app.

If it's for a new project, you can basically do what you want.

For example, you can make your controllers like this

src
   - Controller
      - Bundle1 //Bundle is not the right word here, it's just to say you can separate your code in independents parts like this
      - Bundle2

Same thing for logic Classes, Models (Entity/Document), etc., etc.

You just have to change the services.yaml file to indicate where are your controllers and define in which folders you have Service (Injectable Classes) etc.

You're basically free to do whatever you want, even if it's recommended to follow their Demo App (src/controller/*, src/Form/*, etc.)

The question is old and I hop it will still help you.

-1
votes

Every large project should split into backend, frontend, and api or services, and a well format variable key , error code key and cache key control between there, so each project shall has own dependency, it cut time in maintenance, hour of develop, etc ...

backend.mysite.com

www.mysite (frontend)

api.mysite.com