I have a bundle I am working on. In the extension for configurations, I am dependant on a service defined in a different bundle, but I get messages that the service is not defined. What can I do to call the services from the other bundle?
EDIT: Here is how I am trying to get the session service.
This is the bundle extension (simplified)
class BundleExtension
{
function load()
{
$this->container->get('bundle.service');
}
}
And here is the services.yml that I am using (again, simplified)
services:
bundle.service:
class: ServiceClass
arguments: [ #session ]
The error I am getting is:
InvalidArgumentException: The service definition "session" does not exist.
Related
I have a controller, let's say Acme\ShopBundle\Controller\ProductListController
And its definition in services.yml is as follows:
services:
Acme\ShopBundle\Controller\ProductListController:
class: Acme\ShopBundle\Controller\ProductListController
arguments: ['#product_service']
Which throws this in my log file:
User Deprecated: The "Acme\ShopBundle\Controller\ProductListController" service is private, checking for its existence is deprecated since Symfony 3.2 and will fail in 4.0.
Followed by
User Deprecated: The "Acme\ShopBundle\Controller\ProductListController" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.
The stack trace list of files is completely inside vendor/symfony so I'm assuming something is misconfigured, but stumped as to what. Any help appreciated.
Controller service must be public:
services:
Acme\ShopBundle\Controller\ProductListController:
public: true
arguments: ['#product_service']
Why aren't you using autowiring anyway? You could register all of your controllers then:
Acme\ShopBundle\Controller\:
resource: '../src/Acme/ShopBundle/Controller' # mutatis mutandis
tags: ['controller.service_arguments']
Kindly read about new features regarding dependency management in Symfony 3.
Hoes does Symfony resolve the Sylius service sylius.controller.shop_user service to the controller class file Sylius\Bundle\UserBundle\Controller\UserController.
My understanding is that sylius.controller.shop_user is a service, and that in Symfony there will be a corresponding service configuration. This service configuration will tell Symfony which class to use when it needs to instantiate the service.
However, I can't seem to find a sylius.controller.shop_user configuration in the Sylius source configuration anywhere. There's just references to this service in routing files
#File: src/Sylius/Bundle/ShopBundle/Resources/config/routing/ajax/user.yml
sylius_shop_ajax_user_check_action:
path: /check
methods: [GET]
defaults:
_controller: sylius.controller.shop_user:showAction
_format: json
_sylius:
repository:
method: findOneByEmail
arguments:
email: $email
serialization_groups: [Secured]
or in on-disk container cache files.
var/cache/dev/srcKernelDevDebugContainer.xml
1798: <parameter key="sylius.controller.shop_user.class">Sylius\Bundle\UserBundle\Controller\UserController</parameter>
15230: <service id="sylius.controller.shop_user" class="Sylius\Bundle\UserBundle\Controller\UserController" public="true">
So how does Symfony know to instantiate the right class for this service?
Is there configuration I'm not seeing? Some Symfony magic that auto-generates the class? Some other mysterious third thing where I don't know what I don't know?
I don't have any specific task in mind, I'm just trying to get a feel for how Sylius and Symfony work under the hood.
The controller service is defined based on ResourceBundle's configuration in Sylius\Bundle\ResourceBundle\DependencyInjection\Driver\AbstractDriver::addController. This driver is called when loading a bundle.
Services with the name sylius.controller.[entity-name] are part of the
Sylius
entity resource system. As best I can tell, when you define your new doctrine entities
in a specific way and
register them as a Sylius resource, Sylius will
automatically generate these controller services based on your
configuration.
The actual line of code that defines these services
is here.
#File: src/Sylius/Bundle/ResourceBundle/DependencyInjection/Driver/AbstractDriver.php
/* ... */
$container->setDefinition($metadata->getServiceId('controller'), $definition);
/* ... */
The
Sylius\Bundle\ResourceBundle\DependencyInjection\Driver\AbstractDriver
class is a (as of 1.3) a base class for the
Sylius\Bundle\ResourceBundle\DependencyInjection\Driver\Doctrine\DoctrineORMDriver
class. How this class ends up being used is by Symfony is unclear, but is
fortunately beyond the scope of this answer.
I have an service class with the class name NewsService.
The service is configured as follows:
services:
portal.news:
class: xxx\NewsBundle\Service\NewsService
arguments: ["#doctrine.orm.entity_manager"]
I use Phpstorm with symfony plugin - The plugin finds the service, but Symfony itself does not.
I get the following error message:
An exception has been thrown during the rendering of a template ("You have requested a non-existent service "portal.news".").
How I use the service:
{{ render(controller('xxBundle:Widget:renderNews', {'slice_length': 250})) }}
in the Controller xxBundle:Widget:renderNews: $articles = $this->get('portal.news')->getNewestArticles($count);
cache is cleared
I checked everything (wrong service configuration, bundle is loaded, syntax is ok, ...)
You probably forgot to set public: true to your service, because since 3.4 all Symfony services are private by Default.
Also, you should avoid $this->get() functions and prefer fetching directly your service from your controller arguments
<?php
use xxx\NewsBundle\Service\NewsService
class MyController {
public function myAction(NewsService $service) {}
}
Using Service that needs an argument, you need to declare your service as an alias https://symfony.com/doc/current/service_container.html#explicitly-configuring-services-and-arguments
I am trying to write my own messages to the log in Symfony 2.3, from anywhere, and not just the Controller (which I realize you can just do a "$this->get('logger')".
I've seen that in Symfony 1 you can use sfContext, but that class no longer seems to be a viable choice in 2.3.
Any help is appreciated.
Symfony2 has Service-oriented architecture (http://en.wikipedia.org/wiki/Service-oriented_architecture) and logger is one of service (by default Monolog). In controller you have access to service via $this->get('service_name'). Here is more info about service container: http://symfony.com/doc/current/book/service_container.html#what-is-a-service-container. If you wanna use logger in another service you have to define service and inject logger service. Example:
# section with defined service in your config.yml file (by default in config.yml)
services:
# your service name
my_service:
# your class name
class: Fully\Qualified\Loader\Class\Name
# arguments passed to service constructor. In this case #logger
arguments: ["#logger"]
# tags, info: http://symfony.com/doc/current/components/dependency_injection/tags.html
tags:
- { name: monolog.logger, channel: acme }
Additionally you should familiarize with dependency injection docs: http://symfony.com/doc/current/components/dependency_injection/index.html
I hope that helped. If not, please let me know where exactly you want to use logger.
I want to log into a different file than the usual dev.log or prod.log
I know that this can be done with different channels and I used it in several services, but I'm not very clear about switching the Monolog channel in a controller.
In a service you just define the channel via the tags attribute in the service definition, but how can I do this in a controller or even better in a specific action?
I know that a possible solution would be this: Symfony 2 : Log into a specific file
But it seems overkill to define two new services just for logging to a custom file.
The only way to do this is to define your controller as a service and inject a custom logger with a custom channel.
Since the channels are created automatically there is currently no other way, but it's an interesting request and you're not the first, so I created an issue on MonologBundle to allow the definition of channels at the bundle configuration level. That way you could just fetch the proper logger from the controller using $this->get('monolog.logger.mychannel') (which you can already do if the channel exists, but not if you want a custom channel for the controller that nothing else uses).
Update:
As of symfony/monolog-bundle 2.4.0 you can define additional channels as:
monolog:
channels: ["foo", "bar"]
Then you can retrieve it as $this->get('monolog.logger.mychannel')
I know that this is an older post, but I ran into a similar need using symfony/monolog-bundle 2.1.x. I couldn't seem to find exactly what I needed in other threads, so I'm documenting my solution here, which was to create a logger container that used a custom channel.
In config.yml
monolog:
handlers:
user_actions:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%-user-actions.log"
level: info
channels: [user_actions]
In my bundle's services.yml
acme.logger.user_actions:
class: Acme\MyBundle\Monolog\UserActionsLogger
arguments: ['#logger']
tags:
- { name: monolog.logger, channel: user_actions }
In src/Acme/MyBundle/Monolog/UserActionsLogger.php
<?php
namespace Acme\MyBundle\Monolog;
class UserActionsLogger
{
public $logger;
public function __construct($logger)
{
$this->logger = $logger;
}
}
Then you can either inject the logger container into another service with:
acme.user.authenticationhandler:
class: %acme.user.authenticationhandler.class%
public: false
arguments: ['#router', '#security.context', '#acme.logger.user_actions']
Or, you could selectively use the logger container as a service in any controller:
$userActionsLogger = $this->get('acme.logger.user_actions');
Then you can access the actual logger by:
$userActionsLogger->logger->info('A thing happened!')
I am currently using symfony/monolog-bundle 2.3.0 and the following code works.
Configuration in config.yml
monolog:
handlers:
main:
type: stream
path: %kernel.logs_dir%/%kernel.environment%.log
level: info
doctrine:
type: stream
path: %kernel.logs_dir%/doctrine_%kernel.environment%.log
level: debug
channels: doctrine
On Controllers
$doctrineLogger = $this->get('monolog.logger.doctrine');
Hope it helps.