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
Related
So I'm finally taking this bull by the horns and moving from 3.4 to 4.x and one of the undocumented (?) steps is that previously, all my code was supposed to live in separate bundles per function on the site (at least this was recommended).
Now, suddenly all my code is expected to live inside one bundle (src) and I understand some already had this approach previously, using only the AppBundle with no subdirectories. Obviously this will mess things up when moving from several bundles into one. For one thing, there are several files called DefaultController.php (one per bundle, as I have a LogBundle, a FinanceBundle, a UserBundle etc.
Is there a nice guide to how this move is best made, what paths need to be changed where etc.? Seems like the symfony guys considered this a small little change and no reason to provide a step-by-step, I find it quite annoying 😐 or perhaps I'm just stupid 😂
According to this guide https://symfonycasts.com/blog/AppBundle no code changes are necessary, but my app breaks all over the place when moving files into another directory structure, I suspect routes to templates will need modification, routes to controllers etc.
It also seems that every single Entity relationship breaks when the path to the entity's php file changes...
Rewireing this is a major job, I don't understand why this isn't adressed anywhere?
And while the site referenced above mentions that up to 4.0 your own code resided in several bundles, it seemes that the sample code from sensiolabs silently changed from ACME/DemoBundle to AppBundle between versions 2.4 (https://github.com/symfony/symfony-standard/tree/2.4/src) and 2.5 (https://github.com/symfony/symfony-standard/tree/2.5/src) without any instruction to change your own directory structure to mimic that back then (https://symfony.com/doc/2.5/cookbook/upgrading.html).
So confused 😂
Currently my directory structure looks like this
In one Symfony bundle I define a compiler pass to preprocess some configuration. Part of that config is based on Doctrine entities, so I need to get the full metadata information for all application entities.
The compiler pass is executed very late (PassConfig::TYPE_BEFORE_REMOVING). I'm using $container->get('doctrine') like this to get the entity metadata:
$em = $container->get('doctrine')->getManagerForClass($entityClass);
$entityMetadata = $em->getMetadataFactory()->getMetadataFor($entityClass);
However, this is causing random failures for some users because of the use of the doctrine service during the Symfony container compilation.
I'd recommend to change your entities addressing. Mainly - create your models with interfaces and make entities implementing them.
Using resolve_target_entities Doctrine will "convert" them to the particular classes.
An example code is here: https://github.com/Sylius/SyliusResourceBundle/blob/master/DependencyInjection/Compiler/DoctrineTargetEntitiesResolverPass.php
Just make sure your bundle is registered before DoctrineBundle is registered.
Then - in your whole app - instead of AppBundle::Entity addressing, use FQDN of interface bound to an entity earlier.
I've experimented a bit with compilers and services and it's a very bad idea to base on cross-bundle services under compiling container process... Why? It's not reliable - sometimes it will work as you want, sometimes it will fail as you described.
Thank you all for your comments and ideas. I post an answer to explain how I solved this problem.
Trying to use the Doctrine service in a compiler pass was creating more and more problems for our users (and it was creating other minor issues with other services such as Twig). So this was definitely a bad solution for our needs.
So at the end I decided to change everything. We no longer use a compiler pass to process the configuration and instead we use a regular PHP class called during runtime.
In the dev environment, the configuration is processed for each request. It's a bit slower than before, but we prevent any caching issue. In the prod environment we use Doctrine Cache to process the configuration once. Besides, we've create a cache warmer to create the cached configuration before the first request hits the application.
Is there a standard way in symfony + propel to manage changes to the database model in a situation where
the application has a number of separate variants (one for each specific customizations):
core application: code + datamodel
|- variant1: specific code + specific datamodel changes
|- variant2: specific code + specific datamodel changes
...
mulitple developers work at separate parts of the application and therefore also at separate parts of the datamodel
Problems happen e.g. when parts of the datamodel are interdependent (foreign keys) and developers write migrations and oversee these inderdependencies. And since the variants are parallel to each other it becomes increasingly difficult and error prone to keep trak of and write migrations.
I know that this is a what management is all about, but I'm wondering whether there are automatic? ways (- or completely otherways not using propel or using subversion etc. to make checks) that make sure that problems are reduced, ideally to zero.
Basically, I would like to know if there are enterprise grade practices / standards for using symfony and ORM (for symfony 1.4 or 2; propel) that manage multiple developers + multiple variants of the application?
Thanks :)
Propel2 supports parallel migration, means you can have different migration files in different development branches.
So you're just creating migration files based on your changes and new code as usual and commit all that stuff which results basically in having some migration files in branchA and other in branchB. When a branch will be merged to master you can just call the migrate:migrate command at master and are ready to go.
When you switch from branchB to branchA you need to make sure to downgrade the migration in branchB until you have the same base as branchA. Then switch the branch to branchB and do migrate:migrate.
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.
I have a large number of services that my team are building and the auto-generated metadata is getting a bit unmanageable. To combat this, I created a project as a nested site (or sub-site) of the root. This works fine on my IIS local, but doesn't seem to work on a server-based IIS. Is it possible to get URLs like the following:
- http://server/WebServices [Root Project]
- http://server/WebServices/Project1 [Sub Project 1]
- http://server/WebServices/Project2 [Sub Project 2]
I know that using the routes in the AppHost I can get this effect but the resulting metadata is starting to get huge as they're all in one site. What I want is to be able to manage separate services in separate projects and have them come out in a hierarchy similar to above.
Look into the implementation of Routes.AddFromAssembly() extension method which goes through all the services are registers routes with the following conventions:
/{requestDto}
/{requestDto}/{Id}
On each of the HTTP Verbs that are implemented.
You should be able to implement your own conventions using a similar approach.