Obtain the full configuration of a service including its parameters - php

php app/console container:debug does not give enough information on the services.
1 - What parameters are injected during the creation of a service?
If I want to know what parameters are injected into the service form.factory for example, is there a command for this?
php app/console container:debug form.factory does not give the list of parameters.
2 - Is there a way to find the location of a service (meaning the file where it actually is declared)?
It could be either:
a services.yml file
a services.xml file
through the DependancyInjection\Configuration.php file
But which one?

What parameters are injected during the creation of a service?
This does not exists yet, however I have planned to create a Pull Request for this for Symfony2.2
Is there a way to find the location of a service (meaning the file where it actually is declared)?
No and you won't get a feature like this. The code is not able to get the location of the file.
What you can do is locate in which bundle where the service is declared. All services from the core framework are declared in the SymfonyFrameworkBundle. You can find the service configuration in #bundleroot/Resources/config. The form.factory service is loctated in #SymfonyFrameworkBundle/Resources/config/form.xml.

There is a tool: http://jmsyst.com/bundles/JMSDebuggingBundle
It partly answers to your needs, by dumping dependencies of a given service.
However, it does not says where a service has been defined.

Related

How to use my own service definition for a security firewall guard in Symfony 4.2?

I have a service defined in services.yaml that has a calls entry since I don't want to specify my dependencies in it's constructor so I use setters.
Now I am trying to point the security.firewalls.main.guard.authenticators.0 configuration entry to it, but if I try to reference it like this: '#App\Service\Authentication\Guard' I get The service "security.authentication.provider.guard.main" has a dependency on a non-existent service "#App\Service\Authentication\Guard".
If I specify just the name of the class as per Symfony's docs: App\Service\Authentication\Guard then there's no exception and the guard works, however the calls section of my definition is completely ignored and thus my setters don't work.
My best guess would be that the security module uses it's own service locator that's somehow disconnected and ignores definitions in services.yaml, which is probably why you won't find examples of the above config entry using simple service names rather than canonical class names.

symfony 4.1: no such service exists

So I've created a new Symfony 4.1 project last week and have been working on it without any issues. Until yesterday when I started using some third party dependencies. I installed the Guzzle Client by using the composer require guzzlehttp/guzzle. This installed the package just fine as far as I can see.
However, when I then try to inject this service into a constructor in my code (an event or command), I get the error message: Cannot autowire service "App\xxx\Command\testCommand": argument "$client" of method "__construct()" references class "GuzzleHttp\Client" but no such service exists.
The Guzzle service is not the only one that doesn't work, this is just an example. The weird thing to me is that there are a lot of dependencies that I have that work just fine like the Doctrine DocumentManager, JMS serializer and NelmioApiDocBundle.
What I've tried so far (and actually semi-solves the problem) is adding the service name to my services.yaml file:
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.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
GuzzleHttp\Client: <-- Adding this makes it work flawlessly.
The problem I have with this solution is that I would end up adding hundreds of services to my services.yaml file just to get them to work. It seems to me like this is not the optimal solution.
So my question is how I could resolve this in the most elegant way. Is this something I'm doing wrong in my project? Is it something that has to be resolved on the vendors side? And if so, how could it be made to work with Symfony 4.1?
composer require GuzzleHttp\Client
It seems like you are trying to require a class, not a package. I was not aware composer is smart enough to recognize a package by it's provided classes, so I checked... it can't, only gives package name suggestions.
Make sure you understand what is a composer package.
The Guzzle service is not the only one that doesn't work, this is just an example.
You don't have a Guzzle service. You only have the guzzle library with it's classes. Services require a service definition, like the one you wrote.
The other services like Doctrine you mentioned are working, because they are bundles, which provide service definitions.
Either you use a bundle, or you use a library, and hook it up yourself.
In the case of guzzle, I would not use a bundle. Then again, I would not use guzzle directly anymore, but HTTPlug. (bundle: https://github.com/php-http/HttplugBundle, library: https://github.com/php-http/httplug)
In my case, I just needed to re-generate the optimized autoload files.
So using composer dump-autoload solved the issue for me.

Symfony: Accessing parameters without container or static configured service

We have a project we're migrating to Symfony 3.3 and the new DI configuration. We have a service that used to be passed values from parameters file based on an argument supplied to the command. (bit more complex than this but you get the idea):
$this->service->setOptions($this->getContainer()->getParameter('account_'.$accountId));
With the migration we want to stop making the commands ContainerAwareCommand as we can now use new DI for the services. However, this leaves us stuck working out an alternative method of fetching the parameters when we cannot statically configure them in services.yml
Would it be best for me to just use the Yaml component and read the parameters.yml file in manually for this or is there some other, more appropriate solution?

How to handle config files in PHP library

I wrote a small library (https://github.com/dborsatto/php-giantbomb) that acts as a wrapper for an API. In order to work, the library needs 2 basic configuration options:
An API key
A file that describes the API options
What is the suggested way to handle these two files?
The API key is of course personal so it can't be added to the repository. But by doing so, I can't write a functional test for the library as a whole, thus limiting myself to only unit tests for the single parts. Do I give up the functional tests altogether or is there a way to make this work?
About the other config, basically it's a YAML file (https://github.com/dborsatto/php-giantbomb/blob/master/api_config.yml) that includes the base API endpoint, and configuration for each data repository. At the moment this is handled by a Config class that is decoupled in a way that the user must write glue code and inject data into the Config. This way it's easier to test, but as a whole I feel like it's creating a bigger disadvantage than just letting the Config class load the file, parse it and behave accordingly. What is the best way to do this? At the moment there are no tests in the repository, but I'm working on it (along with some code refactoring).
I would suggest to leave the configuration outside your library; I've done something similar for the Mandrill mailing service, where I left to the developer the management of the configuration (I was working in a Symfony 2 project). For me there is no Config class, just the service constructor that accepts the API key and an (optional) array of options:
public function __construct($api, $options = array())
{
// My code
}
When I need to use my service inside the Symfony 2 application, I take the needed parameters and configuration from a place (Symfony's config files) external to my service; this way I can decouple the library from the configuration. Of course the service contructor throws an exception if the mandatory parameters are missing.

Where in Laravel 4 to declare new location and new namespace

I am trying to create an alternative view and found this answer:
How to load view from alternative directory in Laravel 4
which suggested using this code
View::addLocation(app('path').'/themes/default');
View::addNamespace('theme', app('path').'/themes/default');
But cannot decide where to declare these statements . In which file can I use this code?
start.php,path.php,app.php,global.php or in another file .
If using the app/config/view.php configuration file to add view loading locations (via the paths array) is not enough for your needs, you can probably fit that into a service provider.
Laravel actually uses the View Library's Service Provider to register the view paths locations (based on the app/config/view.php config file as mentioned).
One thing you can do is add your own service provider class and add in your view logic there, in order to add a location / namespaces as you need. (You can even have your service provider read your own configuration files in order to determine locations/namespaces).
If you need help creating a service provider/don't know where to put one, read this on creating a Laravel application library.
If that's all you'll be doing, putting it inside app/start/global.php works just fine. There's really no need for a new service provider for such a simple task.
However, if after some time you realize your global.php file is starting to get too heavy and messy, then you should go for a service provider, as #fideloper mentioned.

Categories