Symfony Folder Structure Standard - symfony

Is there someone who can explain in detail the standard used by Symfony* to name folders and files in the directory structure?
MyBundle
├─ Controller/ <-- 1) why singular?
├─ Model/ <-- 2) why singular?
├─ Resources/ <-- 3) why plural?
│ ├─ config/ <-- 4) why the "c" is lowercase?
│ ├─ translations/
│ ├─ views/ <-- 5) why the "v" is lowercase and views is plural?
│ │ └─ Default/ <-- 6) Why uppercase?
│ │ └─ my_view.html.twig <-- 7) Why lowercase and snake case?
│ └─ public/
├─ Service/ <-- 8) why singular?
└─ Tests/
This leads to another question: if I want to create a folder which contains ArchiveSection classes inside the Model folder, how should I name it?
Model/ArchiveSections/
Model/ArchiveSection/
Model/archive_sections/
* I am using Symfony 2.3.

See the docs talking about bundle directory structure.
I would say just keep in mind that the Resources directory structure must follow the standards to get some automatic registration of view paths and translations files in the kernel. The same applies to the Command directory.
For the rest it's how you want it to be, just know that the directory structure should repeat the symfony components structure to keep logic and readability (a Twig directory for creating twig extensions or functions, a Serializer directory to hold custom normalizers...).
This is relevant to have a good directory structure as it defines your classes namespace structure.

There is no strictly rules for structure and architecture directory in symfony framework. But exist best practices and standard convention.
In your case, there is nothing issue and you can do what do you want.
It seems that underscore in name directory is not very standard convention but not mandatory.
For question deal with singular or plurial it seems that is unanswered convention from symfony developers. Example : Me I name my service directory with plurial like this 'services' and all my code run perfectly with this name.

Related

Sass not finding correct filepaths

I want to use sass to write individual components, for example styling a chart. But I don't want to manually include every component, but rather have one scss file that includes all the components and then gets compiled to one .css file that I can include. I found this SO answer but it didn't work for me and according to SASS, you're not supposed to use #import anymore. This is the project structure:
src/
├─ about/
│ ├─ .../
│ ├─ scss/
│ │ ├─ chart.scss/
├─ app/
│ ├─ scss/
├─ build/
│ ├─ css/
| | ├─ styles.css
├─ base/
│ ├─ styles.scss
styles.scss should include all scss files from all projects in the src, and should be compiled on every .scss save. When I do it with this command though:
sass base/styles.scss:build/css/main.css --watch --style=compressed --no-source-map
it gives the error:
Error: Can't find stylesheet to import.
╷
1 │ #use "//about/scss/chart.scss";
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
╵
base_templates\styles.scss 1:1 root stylesheet
The content of styles.scss is
#use "//about/scss/chart.scss";
and that of chart.scss:
h1 {
color: #fff;
}
(as a test). What am I doing wrong?
The path should be "/src/about/scss/chart.scss" for Sass if src is the source of the volume respectively partition. Sass never 'knows' anything about your domain or network, therefore you can't assume that you can use paths based on the webroot as absolute paths.
You can also consider using relative paths, then it would be '../about/scss/chart.scss'.

Batch renaming files into sub directories

I have files as follows:
assets/
├─ icon_1.png
├─ icon_1#2x.png
├─ icon_1#3x.png
├─ icon_2.png
├─ icon_2#2x.png
├─ icon_2#3x.png
and I want to change it to this format:
assets/
├─ icon_1/
│ ├─ 3.0x/
│ │ ├─ icon_1.png
│ ├─ 2.0x/
│ │ ├─ icon_1.png
│ ├─ icon_1.png
├─ icon_2/
│ ├─ 3.0x/
│ │ ├─ icon_2.png
│ ├─ 2.0x/
│ │ ├─ icon_2.png
I am trying to use zmv commands such as
zmv '(*).png' $1/'$1.png'
or
zmv '(*).png' '$1/$1.png'
to get a feel of how it works. However, it tells me that I do not have the right directories. Is there a way to create directories dynamically from the file names?
I wasn't really able to find a way to parametrize the suffixes and create the directories dynamically, however I did find a solution for my specific case of the problem.
I ran the following commands on zsh:
for file in *#3x.png
do
dirname="${file%#3x.png}" #this truncates the #3x.png from 'icon_1#3x.png' and so on
mkdir "$dirname"
mkdir "$dirname/2.0x"
mkdir "$dirname/3.0x"
done
This creates the folder structures that I want. Now I only have to move the files from ./ to the desired directories as follows:
zmv '(*)#3x.png' '$1/3.0x/$1.png'
zmv '(*)#2x.png' '$1/2.0x/$1.png'
zmv '(*).png' '$1/$1.png'
I move the ones with #3x, #2x suffixes first so they don't get selected by the (*).png selector.
This can be done with zmv, but you may need a somewhat complicated pattern. This will move the files if the destination directories exist:
zmv -n '(icon_<->)(*).png' '${1:r}/${${2##}%x}${2:+.0x}/$1.png'
The -n (no-execute) option is for testing - remove it to actually move the files. The extended glob pattern <-> matches any number; it lets us split the source pattern into two pieces. The destination pattern uses several zsh parameter expansions to build the path, with repeated forward slashes being treated like a single slash for the icon_1 and icon_2 directories.
Out-of-the box, zmv will not create directories, but it will accept a custom command that can call mkdir:
mkdir_mv () {
mkdir -p -- $3:h
mv -- $2 $3
}
zmv -n -p mkdir_mv '(icon_<->)(*).png' '${1:r}/${${2##}%x}${2:+.0x}/$1.png'
The mkdir_mv code is from this answer.

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

In the Symfony Best Practices is advised to not use bundles to organize business logic.
The bundles should be used only when the code in them is meant to be reused as-is in other applications:
But a bundle is meant to be something that can be reused as a
stand-alone piece of software. If UserBundle cannot be used "as is" in
other Symfony apps, then it shouldn't be its own bundle.
So, as I'm upgrading my app from Symfony 3.3 to Symfony 4, I think this is the right time to reorganize my code.
At the moment I have followed the "bundled-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 should have I to organize my code?
I'd like to organize it this way:
-src
- Core
- Controller
- Entity
- Repository
- ..
- Todos
- Controller
- Entity
- Repository
- ..
- Catalog
- Controller
- Entity
- Repository
- ..
- Cart
- Controller
- Entity
- Repository
- ...
But, is this correct? Is there any problem with the expected folder structure of Symfony 4 and Flex?
Or is better something like this:
-src
- Controller
- Core
- Todos
- Catalog
- Cart
- ...
- Entity
- Core
- Todos
- Catalog
- Cart
- ...
- Repository
- Core
- Todos
- Catalog
- Cart
- ...
- ...
The same applies also to other root folders as described in the project directory structure (about how to override it).
Are there any rules or constraints that I have to take into account deciding my new folder structure?
TRYING TO SOLVE THE PROBLEM
So, trying to solve the problem, I'm going deeper in the documentation and I will write here what I will find.
Controllers: Use a fine grained configuration of controllers.
Twig:
Entity: Use orm.entity_managers.some_em.mappings.mapping_name
Conway's law:
organizations which design systems ... are constrained to produce
designs which are copies of the communication structures of these
organizations.
You should design your directory structure around how you organize work.
If you or your colleagues work full-stack on per feature basis you should group your code per feature. It will make navigation and code discovery easier.
If you or your colleagues are well specialized on back-end, front-end, translations etc. you should organize your code around that. Directory structure on per function basis will support clear split of responsibilities.
Also, the depth should depend on how big do you foresee a project to be. If it will be a 5+ years effort of 5+ people, you should probably go with splitting both on per feature and per function with nesting, as mentioned, depending on work organization. If it will be a 3 month project for one person i.e. some simple internal tool you should probably go with more flat structure. I would also recommend sticking to defaults.
Additionally, I found this article informative: https://blog.nikolaposa.in.rs/2017/01/16/on-structuring-php-projects/
2nd structure is quite suitable for complex app, business areas splitted.
It is easy with Symfony 4 to configure its application in 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 bit of configuration : service auto-wiring, 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']
As stated in comments, Symfony can work well with all these structures, so indeed we cannot have an accepted anwser here, but here is my two cents.
To be honest, the best practices would be to organize architecture independently of the framework (it is mainly for this reason that Symfony 4 no longer imposes a bundle).
But in fact, except for really specific or complex projects, it will be more practical to have a "symfony-oriented" organization.
What follows is my personal preferences, and are also strongly influenced by the typology of my projects (CRUD oriented, Rest API, without strong business logic)
In general, I'm moving towards a structure like this:
-src
- Controller
- Core
- Todos
- ...
- Entity
- Core
- Todos
- ...
- Repository
- Core
- Todos
- Validator (or other Symfony oriented components)
- Core
- Todos
- Others (depend on project)
- Core
- Todos
- ...
The reasons are:
Less service definition with autowire - yeah, I'm lazy ;-)
If you need to register your repositories or controllers as services, you can do it with one declaration.
In Symfony Flex recipes, it is usually this structure that is used.
DoctrineBundle for example initialize src/Entity and src/Repository folders and recipes that contains entities also use this structure.
But keep in minde that Symfony Flex is not mandatory. Its purpose is mainly to ease the project's init and make the framework more accessible to beginer

New option asked about Multiple Application when generating a bundle since Symfony 2.8

Before Symfony 2.8 and because I was in need of a multiApp system in Symfony,
I followed these two posts to achieve this :
-http://jolicode.com/blog/multiple-applications-with-symfony2
-http://mihai-stancu.ro/2015/10/03/multiple-apps-in-one-repo-with-symfony2/
It's not really supported by SensioLabs but it works well, with a attached console option (php app/console generate:bundle --app=app1 for example) to select on which app you need to use a command.
I see now since Symfony 2.8 that a new question is asked when generating a bundle :
Welcome to the Symfony bundle generator!
Are you planning on sharing this bundle across multiple applications? [no]:
But I don't find anything about this feature nowhere across the net.
Is it related to a MultiApp functionality ? Any information about that ?
Thanks anyway & Best Regards !
answer of #michael-sivolobov is very Good.
But, I want to add more clarity in answering the Question:
Are you planning on sharing this bundle across multiple applications?
[no]:
The Symfony Bundle generator needs to decide the useage of the generated bundle.
If this question is answered with yes : That means your generated Bundle will be Used "as is" with multiple projects, not Just for your current project, so you need to prefix a "vendor" name for your generated bundle, and also add the prefix to the namespace of the generated bundle.
Upon not following the convention, a message will print from the Console which reads:
Each bundle is hosted under a namespace (like Acme/BlogBundle). The
namespace should begin with a "vendor" name like your company name,
your project name, or your client name, followed by one or more
optional category sub-namespaces, and it should end with the bundle
name itself (which must have Bundle as a suffix).
See Best Practice for Bundle Name for more details on bundle
naming conventions.
Use / instead of \ for the namespace delimiter to avoid any problem.
File structure for the generated Bundle under src/ dirctory will Be:
├─ src/
│ └─ yourVendor/
│ └─ yourBundle/
│ └─ Controller/
│ └─ DependencyInjection/
│ └─ Resources/
│ └─ Tests/
│ └─ yourVendorYourBundle.php/
If you answer this question with a No : This means you intend to use your generated Bundle only for your Current Project, so you do not need the "vendor" name as the prefix as it is never going to be shared.
File structure for the generated Bundle under src/ dirctory will Be:
├─ src/
│ └─ yourBundle/
│ └─ Controller/
│ └─ Resources/
│ └─ Tests/
│ └─ yourBundle.php/
Here is some good documentation on Best Practices for creating projects .
If you don't know how to answer use the default value.
This question is here because you can create bundle for sharing and you must name it with vendor name (like everyone did before best practices had been posted).
But you also can create bundle for internal usage only as a main bundle of your application or some helpful bundle. And so you don't need vendor name in the name of your bundle. And answering no on this question generator will generate you not YourVendorName/AppBundle but simple AppBundle.
Also if answering yes configuration will be generated in xml format while answering no leads to annotation format.
So you don't need to worry about multiple apps if you generate them as separate bundles.

Its better to put Symfony 2 in the "root" of the website (www) or in a sub-folder?

Its better to put Symfony 2 in the "root" of the website (www) or in a sub-folder? And why?
Method 1
mysite/www/...
Method 2
mysite/www/symfony2/...
Thanks you in advance
It is better to put Symfony folder outside of root web server's folder because only web folder of Symfony is meant to be public. By putting whole Symfony folder under root folder of web server you make all files public.
So best solution is to put Symfony folder somewhere outside web server's root folder (like /home/developer/symfonyProject) and then make symbolic link to web folder somewhere under web server root folder (does not really matter if in root folder or sub folder)
/home/developer/
├─ symfonyProject/
│ ├─ app
│ ├─ (...)
│ └─ web/
/var/www/
├─ symfony (this is link to /home/developer/symfonyProject/web)

Resources