How to share the \Mongo instance between Doctrine ODM and MongoDbSessionHandler? - php

I'm trying to use MongoDB to store my sessions, and I need to get a reference to the \Mongo instance.
But apparently it's not declared as a service. Instead, doctrine creates it from within the wrapper.
So what can I do about it? I tried this:
services:
mongo.connection:
class: MongoDoctrine\MongoDB\Connection
factory_service: doctrine.odm.mongodb.document_manager
factory_method: getConnection
mongo:
class: Mongo
factory_service: mongo.connection
factory_method: getMongo
But sometimes it returns null, and it also conflicts with my logger preprocessor that adds the request_id to the logs, which I think has something to do with the session.
Any ideas?

Looking at the source for Doctrine\MongoDB\Connection, the getMongo() method simply returns the $mongo class property, which may or may not be initialized. If possible, you can call initialize() manually before you inject the connection. Given that you're already defining a service for the Connection wrapper, you should be able to do this:
services:
mongo.connection:
class: Doctrine\MongoDB\Connection
factory_service: doctrine.odm.mongodb.document_manager
factory_method: getConnection
calls:
- [initialize, []]
mongo:
class: Mongo
factory_service: mongo.connection
factory_method: getMongo
That would invoke the initialize() method between the container constructing the mongo.connection service from its factory method and it being returned.
Some additional points to note:
If mongo.connection is only going to be used once (to injected into mongo), you may prefer using anonymous service definitions in lieu of defining another service.
The ODM bundle already defines each connection as doctrine_mongodb.odm.%s_connection, using its name from the configuration in place of %s; however, that's not helpful if you need to add a method invocation to the service definition.
The latest version of the ODM bundle (for Symfony 2.1+) changed its service prefix from doctrine.odm.mongodb to doctrine_mongodb.odm, although a BC alias exists for the default document manager. It'd be wise to switch over to the new prefix, though.

Related

Symfony 3.4 controller registered as service throws deprecation warning

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.

how to inject "memcache" to service.yml?

I installed memcache lib and added it to
framework:
session:
handler_id: session.handler.memcache
but when I trying to use it I get this error
[Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException]
You have requested a non-existent service "session.handler.memcache".
You want to use memcache or memcached?
These are two different extensions, so be aware of that.
And I suggest to use memcached, memcache is dead.
Serivce session.handler.memcache is not defined, so you have to define one implementing SessionHandlerInterface, in your case MemcacheSessionHandler.
First, we need to define memcache instance as a service, so we can pass it to MemcacheSessionHandler constructor:
memcache:
class: \Memcache
calls:
- [ addServer, [ %host_parameter%, %port_parameter% ]]
Then, your session handler:
session.handler.memcache:
class: Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcacheSessionHandler
arguments: [#memcache]
You can also use a bundle like cache/adapter-bundle to register a PSR-6 compatible service (or even a symfony cache component, introduced in 3.1) and use Psr6SessionHandler.
If you want to use memcached, it's almost the same configuration-wise.
Symfony has it's own component: https://symfony.com/doc/current/components/cache.html
You have to configure it first in your /config/packages/framework.yaml:
framework:
cache:
pools:
memcached_service:
adapter: cache.adapter.memcached
public: true
provider: 'memcached://memcached:11211'
Now you can inject your Memcached service wherever you want (services.yaml):
App\Service\SomeService:
arguments:
- "#memcached_service"

Symfony2 LiipFunctionalTestBundle overriding #validator service

I am trying to inject #validator into my service but LiipFunctionalTestBundle is overriding that service when it gets injected.
admin.image_service:
class: AdminBundle\Service\ImageService
arguments: ["#validator", "#doctrine.orm.admin_entity_manager", "#image_storage_filesystem"]
Which results in the error
must be an instance of Symfony\Component\Validator\Validator\RecursiveValidator, instance of Liip\FunctionalTestBundle\Validator\DataCollectingValidator given
running php bin/console debug:container results in
liip_functional_test.validator: Liip\FunctionalTestBundle\Validator\DataCollectingValidator
validator: alias for "liip_functional_test.validator"
Is there a way to get around this over than remove liip and refactor all of my tests?
In Your service you should typehint Interface not exact class.
Instdead Symfony\Component\Validator\Validator\RecursiveValidator use Symfony\Component\Validator\Validator\ValidatorInterface - which is implemented by both classes (Symfony and Liip).

Retrieve service from one bundle in another bundle extension

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.

logging in symfony 2.3

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.

Categories