Symfony 5.1 | config/services.php is not working - php

I am implementing the interface autowiring.
The config/services.yaml example works just fine but when using config/services.php instead of config/services.yaml the code in config/services.php does not get triggered.
So this works:
# config/services.yaml
services:
# ...
App\Util\Rot13Transformer: ~
# the ``App\Util\Rot13Transformer`` service will be injected when
# an ``App\Util\TransformerInterface`` type-hint is detected
App\Util\TransformerInterface: '#App\Util\Rot13Transformer'
But this does not:
// config/services.php
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
use App\Util\Rot13Transformer;
use App\Util\TransformerInterface;
return function(ContainerConfigurator $configurator) {
$services = $configurator->services();
$services->set(Rot13Transformer::class);
// the ``App\Util\Rot13Transformer`` service will be injected when
// an ``App\Util\TransformerInterface`` type-hint is detected
$services->alias(TransformerInterface::class, Rot13Transformer::class);
};
Is this a bug or am I missing something?
I also added invalid php code into config/services.php and no error is thrown. So this leads me to conclude that config/services.php is not being ran at all.

Just for a bit of context, starting in 5.1 Symfony has been moving towards using php based config/services.php and routes.php files for configuration in place of yaml files.
However, you need to remove the corresponding yaml file in order to allow the php files to be loaded. You can see this in Kernel::configureContainer().
And in my setups at least, I also find that I have to manually run "bin/console clear:cache" after making changes to either services.php or routes.php. The cache is not being automatically refreshed like it does with the yaml files. Could just be something I am doing wrong.
The php based service and route builders are quite powerful. They give you lots of syntax checking and autocompletion help. Well worth investigating. The docs have side by side examples of yaml vs xml vs php.

Related

I have to replicate all config file for each environment

I try to add some config in config/* directory.
I'll use a very simple example, to illustrate the problem, but keep in mind that this problem occur for every .yaml config files for any services. I am not able to make inheritance between config files.
So in services.yaml I have this code :
#config/services.yaml
parameters:
app.debug: 0
smtp.user: ''
app.locale: '%kernel.default_locale%'
app.product.number_per_page: 20
container.dumper.inline_factories: true
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
bind:
$locale: '%kernel.default_locale%'
$product_per_page: '%app.product.number_per_page%'
And then i try to access $product_per_page into my controller :
#src/Controller/myController.php
public function listProduct(int $product_per_page){
dump($product_per_page);
die();
}
When I execute this code, it give me the following errror :
Could not resolve argument $product_per_page of
"App\Controller\ProductController::listproduct()", maybe you forgot to
register the controller as a service or missed tagging it with the
"controller.service_arguments"?
So I have to copy this config files (config/services.yaml), and then paste it into config/services_dev.yaml, services_prod.yaml, services_test.yaml
And then it is working, but this is not suitable at all...
Because I have to do that for every config files... So i copy and paste in every environnement each time I update ANY configuration.
Of course, I have try to cache:clear and composer update, but nothing do.
I was expecting Symfony read the file as explain here but it is not working for me.
I have try to create another Symfony project, and now it is working in this one. But I want to understand what is wrong ? Is there a thing I have done which have result into a bug that cannot being correct even ater updating Symfony, even after having update composer, even after having clear the cache.
I can't believe there's nothing to do but to create a new Symfony project in which you copy the files from the old one.

Custom configuration file for Symfony project

My goal is to add to a new Symfony 4.4 project an extra config file to define some behavior of the system. It could be anything, like, pancakes.yaml:
pancakes:
enablePancakes: false
I wish to know how can I load that config file. find a way to read its parameters and values to change some custom behavior the system might have but honestly I think I'm not smart enough to understand what the documentation says.
For now it could be anything, like printing the configuration file values, for now I only need to know how to load it.
you can update the following file :
# config/service.yaml
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.
parameters:
locale: 'en'
chat_update_interval: 10000
and use service decoration in your new application to override your parameters.

Fallback route in Symfony 4 while using annotation routing

I'm currently using routing via controller annotations in a Symfony 4 application.
I am trying to route all requests that don't match an existing annotation (e.g. http://example.com/route-that-isnt-defined) to a specific controller and function (e.g. DefaultController::dynamicPage() which has logic to find if I should be serving content or triggering a NotFoundHttpException).
Defining the route for DefaultController::dynamicPage() as #Route("/{param}") precedes and intercepts all other defined routes, making them inaccesible.
I have tried this solution for Symfony 3, not knowing if it will work but get stuck on what "AppBundle" is supposed to refer to, as it's not something that exists in my project.
Currently, my routes.yaml only has one route in it for the index, as all other named routes are defined via annotations:
index:
path: /
controller: App\Controller\DefaultController::index
I am looking for either the proper way to implement the link Symfony 3 solution in Symfony 4, or an alternative method of achieving the routing I want without doing something convoluted like extending the exceptions controller and inserting routing functionality into cases of NotFoundHttpException.
You could try adding a kernel event listener that would handle the kernel.exception event, and for cases where the exception is a NotFoundHttpException you'd return your custom response instead of the 404 Not Found page.
This could be quite flexible since you can implement any custom logic in such listener.
I haven't moved to sf4 yet, but isn't this problem just related to the order of the routes being evaluated? I.e. you could try by just adding explicit definition to load the DefaultController.php annotations in your routes.yml as the last element? I.e. something like this should do the trick (works in sf2.8 at least):
app_annotations:
resource: '#MyBundle/Controller/'
type: annotation
fallback_annotations:
resource: '#MyBundle/Controller/DefaultController.php'
type: annotation
or if that doesn't work in sf4 (if it loads the controller route annotations with some other logic automatically), another workaround would be to just name this fallback controller so that it will be the last one alphabetically (and thus the routes there should be evaluated the last).
From your comment I "smell" you have some composer packages that are not compatible with the current config of your project. Are you upgrading to SF4 from SF3?
I also had this InvalidArguementException:
"The "App" (from the _controller value "App:Default:index") does not exist
or is not enabled in your kernel...
Turns out that I have a non supported package easycorp/easyadmin-bundle version ^3.1 which I fixed it by
Removing the vendor folder
Removing the composer.lock file.
Explicitly specify the version my project supports ^2.3 in composer.json
Run composer install... et Voila!

Symfony: get() - how exactly does this work?

I have a line in a sample Symfony app that reads:
$seo = $this->get('sonata.seo.page');
However the config.yml file reads:
sonata_seo:
page:
metas:
property: ... etc ...
I've read http://symfony.com/doc/current/service_container.html but I'm not clear how exactly the get('sonata.seo.page') works. Does it somehow equate to the key / values in the config file? i.e. does the underscore in sonata_seo get magically changed to a period?
You cannot access values in config.yml direcly, like values in parameters.yml.
That file can store configuration values for bundles thought.
Read more here
What it is 'getting' in this instance, usually within a controller action, is a Symfony Service.
In this instance, sonata.seo.page is a reference to a service, setup in the sonata-project/seo-bundle, which returns an instance of the SeoPage class. Normally, this information is set within your local configuration file (config.yml, or a file that it includes), but the service returns the class that allows you to change the values at runtime.
No service are (directly) defined inside config.yml. It's the bundle that define the service. With $this->get('sonata.seo.page'); you get those.
The config.yml file it's just used to customize the bundles.
The SeoBundle defines the semantic configuration section sonata_seo from config.yml and registers the own Extension of DI container.
Extension implements the load() method. Configuration values from sonata_seo are passed as its first argument.
Method loads various resources including service definition from Resources/config/service.xml:
<parameter key="sonata.seo.page.default.class">Sonata\SeoBundle\Seo\SeoPage</parameter>
...
<service id="sonata.seo.page.default" class="%sonata.seo.page.default.class%"/>
Next, extension set up sonata.seo.page definition with given configuration parameters.
This process will be invoked during the container compilation, when the service definition and its settings will be embedded in the container. Result of this process you can find in the dumped container in the cache directory.
This is a typical scheme of work for the Symfony bundles: define the configuration structure, make an extension, set up the services.

Access to the base_path of a particular Asset directory from a controller

I want to access the base_path (base_url registered) of a specific Asset component directory from a controller in order to store my reports to a specific path preconfigured in config.yml.
I started changing my configuration, after upgrading to Symfony 2.7, like the following:
app/config/config.yml
framework:
assets:
version: 'v5'
version_format: '%%s?version=%%s'
base_path: ~
base_urls: ['http://cdn.example.com', 'https://secure.example.com']
packages:
reports:
base_path: bundles/mybundle
So, when I request a specific route, with the correct request parameters my controller generate the HTML from a particular Twig template and, at the end, it will be converted to PDF using KnpSnappyBundle.
At last, my purpose is to build a list of generated PDF reports accessible from a public assets directory.
$kernel->locateResource()
However, I can access the complete path using a workaround like the following:
$this->container->get('kernel')->locateResource('#MyBundle/Resources/public/reports')
Using parameters.yml
I have also asked for some hints and it seems legit to use the parameters.yml in order to manage the Asset component configuration. So, from the controller, they would be accessed using $this->getParameter() and, at the same time, as a configuration value for Asset.
The simplest way to deal with that is to define it as a parameter in parameters.yml, as you suggested yourself.
It's really easy to get it and it totally makes sense.
Update
I wanted to provide a bit more reasoning for my answer, so I will cite http://symfony.com/doc/current/best_practices/configuration.html as a reference.
Reading there, it seems that you should put into "parameters.yml" all infrastructure parameters which do not really change your application behaviours. I think this applies to your case as well: your application does not change its behaviour according to assets paths, it only needs to know where they are.
So, again, I'd say that putting them in parameters.yml not only provides you an easy solution but also it's a "good practice".

Categories