Override parameters.yml in each bundle symfony2 - php

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

Related

How can I programmatically modify a route from a different bundle in Symfony 3?

I'm using the FOSRestBundle and would like to modify the routes it creates.
I intend to add default parameters to each route the Rest Bundle creates. I've looked through the symfony docs on routing and have found nothing covering this use case.
If there is no way I would either have to
modify the FOS Rest Bundle directly
Or copy its route loader code, make my changes, and add it to my own bundle (and not use the Rest Bundle routing at all.)
I don't like either option.
Does Symfony offer a hook that allow for post processing of routes?
FosRestBundle have a custom route loader. If you look in the github repository you will see that the routes are defined in the RestActionReader.php file. So the only solution is to override it and replace the class associate to the service fos_rest.routing.loader.reader.action

Symfony 2/3 Get Classes in Directory that Implement an Interface

Is there a nice way in Symfony 2 or 3 to load all classes within a directory that implements a particular interface?
Since Symfony 3.3/3.4 it is possible by using configuration only (without a need to write custom CompilerPass):
# config/services.yaml
services:
# ...
_instanceof:
App\HandlerInterface:
tags: ['app.handler']
App\HandlerCollection:
# inject all services tagged with app.handler as first argument
arguments: [!tagged app.handler]
and if you need to restrict services to register from a single directory see importing with resource
references:
https://symfony.com/doc/current/service_container/3.3-di-changes.html#auto-configure-with-instanceof
https://symfony.com/doc/3.4/service_container/tags.html#reference-tagged-services
http://symfony.com/doc/3.4/service_container.html#importing-many-services-at-once-with-resource
Short answer is: you can't.
You don't know, what is in a file until you load it.
Long answer (taking into account what you have wrote in the comment under the question):
The only thing you know before you load a file is its name. So one of solution is to name your modules' classes (and files) with a fixed pattern like UserModule, ProductModule and so on. That way you can load all modules by their names. But this is the solution that I wouldn't suggest.
I my opinion you should change the approach and inverse the workflow. Create a class in which you will define all modules that need to be loaded. In Symfony it's called by default AppKernel, in which you define bundles (modules) to be loaded and initialized.
This has a few advantages.
You can have multiple entry points to your application and configure each one with different modules.
You may have a few different environments (like production and development) with different modules loaded in both of them. (e.g. add some modules in development like profiler)
Also dependency managment is much easier, since you can load defined modules and add their dependencies also with autoloading.
In general I think that you should avoid manual loading any php files (except autoload.php or similar that contains autoloaders) at all.

Load Child Bundle depending on URL in Symfony

I have created a bundle that provide default functionality for some use case.
No I want to direct X URLs to this project. No problem up to this point, all URLs point to the /web folder.
But now I want to create child bundles to modify some functionality / behavior / appearance for each URL. What is the best way to load different child bundles for different URLs?
My approach would be to detect URL in AppKernel and load at this point the specific child bundle. Does it make sense or is there a better way?
Indeed placing your code in the AppKernel seems a good way to handle that but you'll have a cache issue.
Example :
If your Request A loads bundle A, it will be cached.
If your Request B loads bundle B but not bundle A, you'll get an error related to the loading of bundle A's classes.
Another issue will be your routing, you'll have to create separate routing files for your different bundle sets.
My approach would be environment dependent, in your front controller, you'll catch the host and then use a different environment (hosta_dev / hosta_prod / hostb_dev / hostb_prod) for each URL. This will create separate cache and allow you to have separate config / routing files.
You'll still have to make modifications in your AppKernel anyway (for example you'll have to load the "dev" bundles not only if the environment is "dev" or "test" but also if the environment contains "dev" or "test").
Hope it helps.
You can create three services:
main
A which inherited from main
B which inherited from main
Then define in your configuration my_service to main by default.
On Service initialization for controller with url A reconfigure it to A. same for B.

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.

How to access paths and configuration outside Controller in Symfony 2?

I have a problem of not being able to access configuration and path information outside controller context. I am in a Assetic Filter class that has no methods to help me, and I need to know the kernel path along with some configuration. How do I do the Symfony 1 sfContext::getInstance() call in Symfony 2?
If you are writing an assetic filter you are writing a service. In the service definition you can pass parameters from the DIC. For example you can pass the AppKernel absolute path writing:
<argument>%kernel.root_dir%</argument>
If you want to have a semantic configuration for your filter (and for any service in general) it would reside in a DIC extension. By default "MyNamespaceMyBundle" will register the "MyNamespaceMyExtension" extension class inside the DependencyInjection subpackage and this extension will handle configuration from the "my_namespace_my" top level configuration key creating services or setting DIC parameters.
Moreover you would want to have a Configuration class that handles validation, normalization and merging of your configuration. Sadly all of this is more or less not documented anywhere, so best way to achieve your goal is to look at some other bundle (e.g. I learned very much reading FOSUserBundle).
You don't. You must use depency injection somehow. See here why it might have been removed.

Categories