How symfony handles multiple bundles routing? - php

I am trying to understand symfony's routing system.
In app/config/routing.yml, I have two routing configurations from two different bundles
'
firstbundle:
resource: "#FirstBundle/Resources/config/routing.yml"
prefix: /api
secondbundle:
resource: "#SecondBundle/Resources/config/routing.yml"
prefix: /api
`
So if I am making a request like,
https://example.com/app.php/api/images/ (defined in first bundle config)
or
https://example.com/app.php/api/views/ (defined in second bundle config)
How does the router decide which bundle to use?
Suppose I am going to access api./views, in this case will it also check within FirstBundle routing config? My doubt is regarding the routing flow. Does router traverse through every bundle configurations?

Routes, as other configuration parameters, are parsed in the same order they appear in your file.
That means that if two identical routes (keys, speaking more in general) are defined, the first one defined (and so parsed) is the one that is taken.
If you're worry about performances, I can tell that this is not something you should worry about (them are cached)

Related

Override parameters.yml in each bundle symfony2

I'm working on a complex Symfony project. In the project, we have a core bundle which uses the parameters.yml located in app/config.
Each other AppBundle will inherit this CoreBundle and will correspond to a website.
What I need is to have specific parameters in each bundle that will override the default parameters one: when I'll use a route that will bring me into a controller's bundle, the parameters of this specific bundle have to override all the other ones.
I've tried the preprend method but it doesn't fit to this need. It only allows me to create new parameters for this bundle, but not to override the other ones.
I think you misunderstand the idea of bundles in Symfony. Bundle by design should be a reusable module, therefore the configuration placed inside a bundle is the default one. Then it is possible to override parameters (and not only!) in configuration in app folder.
The basic idea is:
Bundles don't use application. Application uses bundles.
So it's completely the opposite to what you expect it to be. Acutally it makes no sense to condition whole application configuration depending on current route since bundles can use one another. What if your currenct action will internally (without redirect) call another bundle's service or even controller?
Also it's worth mentioning that the app folder is the final folder for your application, therefore you can override in it not only bundle's configuration but also other things like services, view templates and so on.
Edit: I forgot to suggest a solution for you :)
Since you want to use custom parameters inside bundle, why do you need the default value in first place? Just create separate parameter namespace for each bundle that won't be overridden by application config. Then use it only inside that bundle.
Solution found thanks to dragoste's asking about separated kernels.
To solve my problem, I had to split the kernels : one for each website.
Documentation can be found here :
http://jolicode.com/blog/multiple-applications-with-symfony2

Symfony2 Routing within a bundle

I have a symfony project where i have seperated my code into two different bundles lets say HomeBundle and AppBundle however the routes are commonly accessible inside both bundle.
eg:- /home defined in HomeBundle can also be accessed from AppBundle
and
/App defined in AppBundle can also be accessed from HomeBundle
what i want is to access /home ONLY from HomeBundle and /App from Only AppBundle I'm looking for 'structuring' my code in a way where i dont have to write any logic to accomplish this, but instead leverage symfony frameworks structure to do this for me, something along the lines of restricting routing to only within the bundle, or some way where the route definition goes 'out of scope' when inside the wrong bundle
im using annotaions for routing, and defined in app/config/routing.yml
edit: the application requires subomain partitions so i'm also using this host/default with placeholder
any help would be appreciated :) thanks
Unfortunately this isn't going to be possible, primarily because of the architecture of Symfony bundles. While separating your code into bundles is good from a cognitive point of view, Symfony doesn't have the concept of being "in" a bundle; what code is run (specifically your controller actions) is usually handled by routes, and routes have to be compiled together from ALL bundles to ensure that a request can be routed successfully.
You would have to write extra code to accomplish what you're asking - my initial thought would be your own Controller class (maybe extending from FrameworkBundle\Controller\Controller) that ran some code before a request (see documentation that may achieve this).
Fundamentally this is an architectural decision for you and my question would be - why do you not want to be able to access /home from the AppBundle? Would a security / role set up work as well or are you trying to sandbox code?
EDIT After some further detail, it turns out that the requirement is for two different actions for the same URL path (e.g. /home) but on different domains e.g. www.example.com/home and subdomain.example.com/home. In this instance it wasn't about code sharing but URLs so Symfony's host/domain based routing solution worked.
I was under the assumption that business logic inside bundles are isolated and would not be 'aware' of routes defined inside other bundles, turns out the routes are globally available to all bundles, i wanted to use the framework of symfony to achieve what i asked for, it happens so there is no way to do it. i probably should use Listeners or before filters etc to achieve this. John Noel answered this.
Luckily for me, the bundles happen to operate on separate Domains (one on the main domain and the other on the subdomain) i noticed this after a chat with #John Noel he suggested matching the Route Based on the Host/Domain. i had this in place previously, upon a second look i figured out i have to -based on the domain redirect all (except for a white list of routes) routes to a controller that throws a 404 exception. Here is what i mean.
Home_restrict:
path: /{slug}
host: "{domain}"
defaults:
_controller: HomeBundle:Home:notfound
requirements:
domain: example.com|www.example.com
slug: ^(?!.*(admin|login)$).*
Routes that appear on top of the list on the page takes precedence, so this should be placed appropriately
You can add a routing.yml per bundle, and include these in your "global" routing:
# src/HomeBundle/Resources/config/routing.yml
home:
resource: "#HomeBundle/Controller/HomeController.php"
type: annotation
and
# src/AppBundle/Resources/config/routing.yml
home:
resource: "#AppBundle/Controller/AppController.php"
type: annotation
then import them in app/config/routing.yml, and maybe even prefix it over there?
# app/config/routing.yml
app:
resource: "#AppBundle/Resources/config/routing.yml"
prefix: /app

Symfony2 bundle based application config merged into global config

I'm currently building a fairly large Symfony 2 application with a number of ever increasing bundles that I'm struggling to keep count of.
I try to keep all bundles specific to each module of the system, which has provided me with a nice easy to manage structure. What isn't so nice is my app/config/config.yml that's very quickly grown out of control. Understand imports can be done within this file which have helped me somewhat but I'd like to move a whole range of config specific to each bundle which should help to keep these bundles reusable within our other applications.
Here of some examples of what I'd like to move to individual bundles.
1) Dependency Injection
We use JMSDiExtraBundle within all internal bundles as we find it makes developing a little bit quicker and easier to manage.
# Annotations/Config
jms_di_extra:
locations:
bundles:
- AppBundle
- BlogBundle
- ContentBundle
- StoreBundle
- UserBundle
I'd like this block to be moved to each individuals bundle config.yml or better yet this would be enabled in each bundles DependencyInjection/AppBundleExtension.php.
2) Routing
Use for route config, but each bundle still needs including within app/config/routing.yml leaving us with a pretty large unmanageable file.
Some examples
app:
resource: "#AppBundle/Controller"
type: annotation
blog:
resource: "#BlogBundle/Controller"
type: annotation
content:
resource: "#ContentBundle/Controller"
type: annotation
oneup_uploader:
resource: .
type: uploader
3) OneUp Uploader
This is my biggest biting point, this configuration is over 500 lines long currently between the 20+ bundles we use. Here are some examples pulled from app/config/uploader.yml which is imported from config.yml. If I could somehow get these into each bundles config I'd be very happy!
# Uploader
oneup_uploader:
mappings:
bundle_name_reference1:
frontend: blueimp
storage:
type: gaufrette
filesystem: gaufrette.local_filesystem
bundle_name_reference2:
frontend: blueimp
storage:
type: gaufrette
filesystem: gaufrette.local_filesystem
My thoughts are by getting all these configs into each individual bundle, I can enable/disable them really easily by just updating AppKernel.php. I'm assuming all of this is possible as Symfony is incredibly flexible, I'm just a little lost when it comes to these lower level alterations.
You could simply just add
oneup_uploader:
#...
to src/Vendor/WhateverBundle/Resources/config/services.yml
OR
There is a cookbook entry on how to decouple bundles from app/config:
How to Load Service Configuration inside a Bundle
I think the ideal, low-coupling, solution would be to create a bundle extending the other bundle (e.g. MyOneUpUploaderBundle) and using the cookbook approach there.

Symfony 2 - "Internal" bundle routing

Is there any way to register bundle's routing from within bundle itself and not importing it in the main routing file?
Now my routing.yml looks like this:
my_route:
resource: "#MyExampleAdhocBundle/Resources/config/routing.yml"
prefix: /
However, I would like to somehow enable bundle routing in ExampleBundle class or bundle config, so it will be on only if bundle is registered in AppKernel.
Have you tried to do this inside your bundle extension file (AcmeDemoExtension for the AcmeBudle) ?
I think you should look inside Kernel::buildContainer to understand how it's done and how you can handle this.
I think custom route loader is the answer.
A custom route loader allows you to add routes to an application without including them, for example, in a Yaml file. This comes in handy when you have a bundle but don't want to manually add the routes for the bundle to app/config/routing.yml. This may be especially important when you want to make the bundle reusable, or when you have open-sourced it as this would slow down the installation process and make it error-prone.
Alternatively, you could also use a custom route loader when you want your routes to be automatically generated or located based on some convention or pattern.
No. For every bundle the routing must be imported in routing.yml. Every popular bundle (like FOSUserBundle) have to do this also.
So no bundle can override users routing. Importing the routes in routing.yml offers the option to define a prefix or host option on this imported routes.

Symfony Routes without app/config/routing.yaml

The tutorials I've read for Symfony 2 instructs users to enter their routing information in
app/config/routing.yml
If users want to have routing information in their own bundles, they're instructed to add a routing.yml file to their Bundle, and then point to their file from app/config/routing.yml with something like
my_route_stuff:
resource: "#CustomstuffBundle/resources/config/routing.yml"
Is there any way to skip the "add this extra configuration to the app/config/routing.yml file? I'm looking for the ability to hand off a bundle to someone else, and have them be able to deploy it into their Symfony application without needing to edit their own app/config/routing.yml.
If this isn't possible, bonus point if anyone can explain why (i.e: the general philosophy behind) routing information is part of the AppKernel instead of the individual Bundles. I'm still a little unclear on the differences between routing.yml files and the normal Symfony config.yml files.
Is there any way to skip the "add this extra configuration to the app/config/routing.yml file?
No, this is the way SonataAdminBundle, FOSUserBundle and a bunch of others handle it.
Why?
Routing belongs to the application, not each and every bundle. If every bundle started including their own routing files and Symfony2 autoloaded them, you would quickly have a mess of routes you may or may not want to enable in your application.
What if SonataAdminBundle wanted you to use /admin, but you already had a route there and wanted Sonata to use /sonata/admin instead? You'd need a file to override those routes and then you're back to square one!
Additionally, although caching mitigates this part, looking up files is expensive and would significantly slow down the development environment. This is why translation files are read from cache even in dev mode and you must clear the cache when you add a new translation resource. See: http://symfony.com/doc/current/book/translation.html#message-catalogues
Finally, leaving the routing out of config.yml is simply a matter of organization. Routing and configuration are two different things and don't belong in the same file.
The general idea is that every file is a thing and should only do that thing.

Categories