I started converting a legacy app over to symfony, my first experience with a php framework was zend, learning zend 1.* to a point where I felt comfortable took me over a year, now I've challenged myself to learn symfony since I find zend 2.* overly complicated.
With zend I was used to just creating a controller class and the view to create a page. With symfony I have to create the route entry, then the controller class and finally the view.
My routes.yml is over 100 lines long with all the requirements, methods and whatnot, and I am about a third into the project.
How can I keep this file organized? Right now it looks very chaotic.
Your site should be split into bundles that represent the section of the site that it concerns (from the site I am currently working on)
AddressingBundle
ChartBundle
ContactBundle
CoreBundle // A bundle that contains all merging items (model, types, etc)
CustomerBundle
PaymentBundle
PolicyBundle
.. etc ...
NOTE: I use YAML for routing. Annotation are available that require no extra files but (possible) means lack of reusability of routes
Within each of those bundles is a set of routing files that can be included or not. Each bundle has a routing file located at Resources/config/routing.yml that links to a selection of files located in Resources/config/routing/.
Then for the main app/config/routing.yml file I can then link to the outer (Resources/config/routing.yml) or internal (Resources/config/routing/something.yml) as needs be. Also it enables you to use the same routes multiples times using different paths depending on prefixes.
UPDATE:
The idea of bundles is to separate concerns. So for me I have (which I have massive stolen from the make up of Sylius) the CustomerBundle that only has a single entity (Customer), then I have the AddressingBundle with a single entity (Address). These can work alone but are attached using the data in CoreBundle. This way if I need to edit the Customer section I just edit CustomerBundle and make sure it interacts in the same way. Technically there is not public and private bundles (due to them all being below root), there are only routes that you make public via your routing and security.
Related
Say I'm going to create few microservices: Alpha, Beta, Gamma.
In terms of Application structure using older Symfony version like 2, I'd create a bundle for each service, but bundles are no longer recommended in Symfony 4. So... Should I create separate repositories for every service or still create a bundles in a one App?
If you have different microservices, as in different applications, you will not need bundles. You can keep them in different repositories, but a common practice is to use a so called mono-repository. As the name suggests, with a mono-repository you keep all of the projects in a single repository. This has the benefit that changes spanning all projects can be done more easily and in sync. The drawback is that it requires more effort when managing and might cause additional overhead when building and deploying as it will not be easy to see which service has changed so must likely you rebuild all of them. There are a few books and presentations on mono-repositories you might want to check out. In short, Symfony does not restrict how you manage your services. You can have a single repository for all projects or multiple repositories.
If you want to serve all "services" through the same application, even without bundles, you can do so by using namespaces to separate the logic, e.g. for controllers:
my_app
- src
- Controller
- Alpha
- IndexController
- Beta
- IndexController
This should work out of the Box with the default configuration and even if you deviate you can make things like argument resolvers work by just pointing the configuration to the correct folder. Obviously this will require you to make sure that code is not shared between services should you ever want to extract them into their own application. There are some static code analyis tools that help you with keeping your architecture clean, i.e. make sure Alpha does not use code from Gamma and vice versa.
If you want to separate the apps more clearly by doing something like this:
my_app
- src
- AlphaApp
- ...
- BetaApp
- ...
You can still do that but it will require more manual work and the recipes will not work anymore, requiring you to do manual changes to most configurations and moving around files. How to do it depends on whether you want a shared kernel or a separate kernel for each service, but if you go that route I recommend keeping separate projects in the same repository, as it will probably yield cleaner results and be less work.
You can still create bundles in symfony4 though its not recommended by best practices. see https://symfony.com/doc/current/best_practices/creating-the-project.html
I created a bundle in Symfony2 that contains my webapp. In there I have some Entities that are mapped to my MySQL-Database. They are located in Acme\MyBundle\Entities.
Now I have created some helper classes that I will not just use in MyBundle, so I outsourced them into a separate bundle (e.g. Acme\MyHelperBundle). Everything is clear until here.
But where exactly do I put business logic files? Do I put them into
Acme\MyHelperBundle\Entities or
Acme\MyHelperBundle\Resources or
Acme\MyHelperBundle\Resources\src
or any other location?
And what would be a good namespace for these helper classes?
create a model folder and in that make a class where you put the business logic and create a service of that class and used that classes anywhere in the project.
I think there's no real rules for that.
if your helper class are declared as services (i think so if you want to use them in all your bundle) you can create a Manager folder. So when i'm on a bundle and there is a Manager, i know that i have some logic that i can reuse everywhere.
It's depend, too, on what you put i your files, but if it's some helper like a UserManager.php on which you create some new request (And you declare it as a service), the Manager folder it's a good place to start.
You can find this folder Manager in many bundle like fosElasticaBundle
ps: sorry for my english, i hope it's clear enough:)
I am developing a multi-tenant capable Symfony2 solution and was wondering if there was a way to use different translations files for each tenant, as the default translations files at present contain e.g. references to the initial tenant's company name, etc.
I am using the Liip Theme Bundle (https://github.com/liip/LiipThemeBundle) to allow tenants to use our codebase, layering their own design on top, but cannot work out a simple and scalable way to allow them to use their own translations files.
There was talk on the theme bundle git repo about this, but I don't believe anything was ever implemented (https://github.com/liip/LiipThemeBundle/issues/12). Ideally I'd like to follow the directory structure they suggested in that thread, e.g.
root
- app
- Resources
- themes
- <theme name>
- public
- translations (this would be new)
- views
as this would allow us to continue the practice of themes being self-contained git submodules that a tenant can maintain themselves.
I ended up using the directory structure I outlined above, and had a console command which symlinked the translations override file in app/Resources/translations. This command ran during my deploy script, and I then created my own "trans" twig function which checked if an override file should be used.
Not the cleanest, but definitely works the way I wanted.
I'm starting with a Symfony2 project. I know the framework basics but I have a question:
Where is the right place to pot those helper classes I create for help or for the business logic?
Max's answer is correct. However I question the path he recommends for your code.
The following classes and files have specific emplacements:
Service Container Extensions (belong in) DependencyInjection/
from http://symfony.com/doc/current/cookbook/bundles/best_practices.html
That says your Services should be placed in a folder called 'DependencyInjection', not 'Services'. In full, it should be src/Foo/BarBundle/DependencyInjection
I say this as someone that had the former and has just finished moving them all to the latter (!)
What #Adam says is wrong, you have to store your Dependency Injection Extensions in DependecyInjection directory, not the services itself. In the documentation says that you can store your (custom) business logic classes in any place you like.
http://symfony.com/doc/current/best_practices/business-logic.html
The best way to keep the business logic is create service to handle all the logic. So it will be in:
src/Foo/BarBundle/Service
and you need to call the service in the services.yml.
I recently did some small work on an existing Symfony2 project. As described by answer from Tuong Le, I created my Helper classes under the Helper directory of the bundle and class name with Helper suffix i.e. the helper class is located at:
src/MyBundle/Helper/MyUtilHelper.php
I can use MyUtilHelper class in my bundle without calling the service container i.e. I didn't need to call.
$container->get('my_util');
I don't really know whether there is some special config. in my setup; someone already got it setup and I was just adding new functionality.
You can create the custom classes under your Bundle, such as under a folder Helper/..
However, to use those helper in your code, you'll need to define those Helper(s) in your service description file (such as services.xml)... Then you can use $container->get('your_helper')->
According to official documentation - in particular - Symfony Best Practices - you should store your services in Utils folder under the src. I belive, that this is correct way regardless of whether you want or don't wont to make the functionality provided by services of your bundle available to other parts of application via Service Container. Furthermore, you can store helper classes in any place you consider suitable. Concerning #Adam Knowles and #PachinSV answers - they are not quite right because they do not answer your question - "Where is the right place to pot those helper classes I create for help or for the business logic?" or "Where to store classes which I want to register and use via Service Container" - but not where to put bundle Extension class - which main purpose is to provide information about configuration which should be automatically loaded from your bundle to apps Service Container during the process of booting the Kernel.
I am a total newbie on Prism. I have been getting to understand a lot from questions on SO and from various Blogs. I am using latest build – V2
I want some explanations on things that may be pretty easy things for you guys but it’s just not getting into my brains (small one for that).
Instead of doing it all right the first time , for which I have spent more than two weeks looking at various blogs, webcast …., I thought to start a project and learn. The amount of information on those hundreds of sites was overwhelming and difficult to digest.
Currently my project is setup like this
Shell -- Menu Module- ViewModel - - -> Menu Service -- -- > Menu Repository --- Data
All are in different assembly
MyShell --- MenuModule ---MyServices -- Myrepository
Shell is required to reference modules ( thought I am sure I can add it using string) later on .
ViewModel has a reference to View - Can live with it for now
View Model requires to use menu service and menu service uses repository
All are built with constructor injection. I have it working now by having module reference MyService and Myrepository projects and then registering types at module level.
But this does not feel good. I don’t want to hard reference any projects. If we are referencing projects why use IoC. In MenuModule.cs ( which is in the root of module) I can register views with unity container
I think I am getting a feel that the answer to this one may lie in the first question
Is Configuration file the answer/
Should I use configuration file for
true decoupling?
If (somehow) we can
register types from code, should we
register types at module level ( I
don’t want to have hard reference to projects)
I need to know the
Interfaces in advance so do you
recommend separate assembly for just
Interfaces?
Bear with me if the questions sound real stupid
You don't need a configuration file for true decoupling. All you need is to register your types in your shell's bootstrapper. I usually break up my projects and refs like this.
Contract Assembly
(Contains only a few simple types and interfaces)
Referenced by:
Shell
Modules
Shell
(Contains concrete implementations of interfaces defined in Contract assembly)
Referenced by:
No one
Modules
(Declares dependencies on interfaces defined in Contracts assembly, for instance IMenuRegistry)
Referenced by:
No one (I use a Directory Module to search for modules in a directory)
Here's a sample project I put together. In this sample I reference the module from the shell for simplicity's sake, but you can remove that reference and use a directory module catalog to load the compiled module at runtime:
http://dl.getdropbox.com/u/376992/CAGMenus.zip
Hope this helps,
Anderson
You're definitely on the right track. Use the configuration file to register your types, and put the interfaces in a separate assembly.