Understanding precedence in Symfony2 chain of imports - symfony

let's say that you have the three following symfony2 config files (extremely simplified), where the file loaded by AppKernel as the current environment is the first one, app/config/config_env.yml:
app/config/config_env.yml:
imports:
- { resource: config2.yml }
- { resource: config3.yml }
parameters:
param: one
app/config/config2.yml:
imports:
- { resource: config4.yml }
parameters:
param: two
app/config/config3.yml:
imports:
- { resource: config5.yml }
parameters:
param: three
app/config/config4.yml:
parameters:
param: four
app/config/config5.yml:
parameters:
param: five
Whenever I refer to param from my code, can you help me understand what is the value associated with param (one, two, three, four or five), and why? Or, in other words, what are Symfony2 precedence rules regarding imports?
Thanks,
Rodrigo

Let's think about what symfony is doing.
First of all, it loads the config_env.yml.
imports:
- { resource: config2.yml }
- { resource: config3.yml }
parameters:
param: one
Next step: Load the imports.
imports:
- { resource: config4.yml }
parameters:
param: two
imports:
- { resource: config5.yml }
parameters:
param: three
parameters:
param: one
Next step: combine them
imports:
- { resource: config4.yml }
- { resource: config5.yml }
parameters:
param: two
param: three
param: one
Next step: Load the imports
parameters:
param: four
parameters:
param: five
parameters:
param: two
param: three
param: one
Next step: combine them
parameters:
param: four
param: five
param: two
param: three
param: one
Now it's important to know that symfony overrides set parameters.
So what's the answer? At the end param is one. Try it.

Related

In Symfony is it possible to if a route matched, forward to other route

I have two routes in two separated bundles: bundleA_route, bundleB_route. In my /app/config/routing.yml I load them as resources like:
bundle_a_routing:
resource: "#SomeABundle/Resources/config/routing.yml"
prefix: /
bundle_b_routing:
resource: "#SomeBBundle/Resources/config/routing.yml"
prefix: /
In most cases this sequence is required, first of all try to match on routes in bundle_a_routing, and then try to match on routes in bundle_b_routing, but in only one case I want to make an exception, I want a single route defined in bundle_b_routing to be matched before the more "concessive" route defined in bundle_a_routing:
route_in_bundle_a:
path: /admin/{path}
defaults: { _controller: SomeABundle:SomeCtrl:someAction }
methods: [GET]
requirements:
path: ^(.*)$
route_in_bundle_b:
path: /admin/download/{formId}/{fileName}
defaults: { _controller: SomeBBundle:SomeOtherCtrl:someOtherAction }
methods: [GET]
requirements:
formId: \d+
fileName: ^([a-fA-F0-9]{32}(?:\.[a-zA-Z0-9]{1,222})?)$
Now the request URI "http://servername/web/app_dev.php/admin/download/12/23d2fff7f606e93acac9ede5b4e2b394.png" matches the first, but I want to match the second...what is the official scenario in cases like this?
You should change the order in which you are importing routes, so the route http://servername/web/app_dev.php/admin/download/12/23d2fff7f606e93acac9ede5b4e2b394.png will trigger the route_in_bundle_b first and the routes that doesn't have the download segment will not trigger it and will trigger the route_in_bundle_a rule.

NelmioApiDoc v3 / Swagger - multiple API docs

NelmioApiDoc v2 allowed to use multiple views parameter so I can hide some endpoints and present them on different URL
https://symfony.com/doc/current/bundles/NelmioApiDocBundle/multiple-api-doc.html
Is it possible to do it in NelmioApiDoc v3 which is using Swagger?
I am using Symfony 3.3
What you are looking for seems to be called "Areas" now in NelmioApiDoc v3.
Thanks to this feature, you can define areas which will each generates a different documentation :
You just have to define those areas in your config.yml:
nelmio_api_doc:
areas:
default:
path_patterns: [ ^/api ]
custom:
path_patterns: [ ^/custom ]
another_custom:
path_patterns: [ ^/anothercustom ]
Then you need to update your routing.yml file:
app.swagger_ui:
path: /api/doc/{area}
methods: GET
defaults: { _controller: nelmio_api_doc.controller.swagger_ui, area: default }
You can read about it on this doc.

Optional Prefix part in Route

I'm trying to create a rather complex-route schema and I'm stuck.
Routes that I wan't to match
/books indexAction
/books/show showAction
/books/authorname indexAction
/books/authorname/show showAction
Current Setup
Routing.yml
actions:
resource: routing/actions.yml
prefix: /books/{authorname}
requirements:
authorname: ".*"
defaults:
authorname: ''
routing/actions.yml
books_index:
path: ""
defaults: { _controller:bookController:indexAction }
books_show:
path: "/show"
defaults: { _controller:bookController:showAction }
This Setup currently matches only:
/books/ indexAction
/books/show showAction
/books/authorname indexAction
/books/authorname/show showAction
but not
/books
The reasons why I split those routes into two files is that in reality the actions contain much more routes, also there is other routing-categories then the actions.
I know I could define the /books route manually without a prefix but I want to avoid this as this schema will be used for many different modules.
You need a /book prefix in any case.
One solution is to define separate entries in your routing.yml for that. One with /books prefix and the second with /books/{authorname}.
index:
resource: routing/actions.yml
prefix: /books
show:
resource: routing/actions.yml
prefix: /books/{authorname}
It's not so elegant, but in this case you can get rid of extra requirements section.
Hope this helps!

How to refer to parameters.yml in services.yml?

Here are params.
app/config/parameters.yml
parameters:
test:
enabled: true
validate: true
And this is service which I want to configure with test param from previous file.
MyBundle/Resources/config/services.yml
imports:
- { resource: "parameters.yml" }
parameters:
services:
my.form.type:
class: My\Bundle\Form\Type\MyType
arguments:
- %test%
Import doesn't work this way. How should I do it?
PS I know I can refer to #service_container. But the point is to pass array explicitly via yaml.
you can ommit ...
imports:
- { resource: "parameters.yml" }
parameters:
... parameters.yml should automatically be parsed and the parameters should be available for injection if you surround them with %.
Try:
services:
my.form.type:
class: My\Bundle\Form\Type\MyType
arguments: ["%test%"]
alias: my_form_type

Symfony2 router - how to call annotation route

Simple case. In my all app I'm using Route annotation driver, defined in routing.yml as follows:
MyBundle:
resource: "#MyBundle/Controller/"
type: annotation
prefix: /someprefix
Some action in MyBundle's Ctrl controller looks like:
#Route("/{page}/{status}", name="default_action", defaults={"page" = 1, "status" = "ok"}, requirements={"page" = "\d+"})
public function defaultAction($page, $status) {...}
Now I want to make this action - default action when visiting my web page. I cannot use just #Route("/") because I'm prefixed. So I'm adding to routing.yml:
_welcome:
pattern: /
defaults: { _controller: MyBundle:Ctrl:default }
And there is where problem starts - Symfony2 is calling default controllers action not from annotation but just from action and I get error:
Controller "...:defaultAction()" requires that you provide a value for the "$page" argument (because there is no default value or because there is a non optional argument after this one).
So simply Symfony2 is not obtaining default values from #Route annotation.
Question is: how to call route for _welcome that is aware of #Route?
You've missed defaults in yml settings, should look like this:
_welcome:
pattern: /
defaults: { _controller: MyBundle:Ctrl:default, page: 1, status: ok }

Resources