How to Access Service Container in Symfony2 Global Helper Function (Service)

How to access service container in symfony2 global helper function (service)?

I assume that the first error (undefined property) happened before you added the property and the constructor. Then you got the second error. This other error means that your constructor expects to receive a Container object but it received nothing. This is because when you defined your service, you did not tell the Dependency Injection manager that you wanted to get the container. Change your service definition to this:

services:
biztv.helper.globalHelper:
class: BizTV\CommonBundle\Helper\globalHelper
arguments: ['@service_container']

The constructor should then expect an object of type Symfony\Component\DependencyInjection\ContainerInterface;

use Symfony\Component\DependencyInjection\ContainerInterface as Container;

class globalHelper {

private $container;

public function __construct(Container $container) {
$this->container = $container;
}

How can I access the symfony Service Container in my Service?

You have two possible solutions :

1. Inject the service container :

<argument type="service" id="service_container" />

And then in your class :

use Symfony\Component\DependencyInjection\Container;

//...

public function __construct(Container $container, ...) {

2. Extend ContainerAware class

use Symfony\Component\DependencyInjection\ContainerAware;

class YourService extends ContainerAware
{
public function someMethod($serviceName)
{
$this->container->get($serviceName)->doSomething();
...
}
}

How can I access the container in a class that is not a service in Symfony 2

Well, you don't have direct access to the controller from inside an object unless you do inject it (which is most likely a bad idea, by the way)... but if you want your kinorm_pdo service available from your User class, just inject that (assuming that you're instantiating the class from a container-aware context):

$user = new User($this->container->get('kinorm_pdo'));

or even

$user = new User();
$user->setPdo($this->container->get('kinorm_pdo'));

Note that it sounds like you're trying to provide access to the database from inside an entity... separation of concerns says this is probably not the cleanest way to accomplish whatever you're trying to do... if you provide a little more information on what you're trying to accomplish, we can probably help you with that, as well.

Symfony2 get service or get container service

There's no difference if you're extending the Base Controller provided by Symfony.

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class YourController extends Controller

If you take a deeper look at the implementation of the Symfony\Bundle\FrameworkBundle\Controller\Controller, you may notice that it provides a get() helper which do exactly the same call as what you did first (getting your service through the container).

So, then,

There's no difference as $this->get('something') simply sencapsulates a call to $this->container->get('something').


Here's the implementation of the get() method you're calling when doing $this->get('main.service');

/**
* Gets a service by id.
*
* @param string $id The service id
*
* @return object The service
*/
public function get($id)
{
return $this->container->get($id);
}

How to access Service container instance from anywhere?

Unless you have a very good reason to do so (very rare situations), you shouldn't directly use container at all. Access to the container from within controllers is provided only for convenience but I would still consider it a bad practice.

In most cases you should register your custom class as a service with dependencies to specific services provided by the framework, 3rd-party bundles or by yourself:

// your service

namespace Acme;

class SomeClass {
private $serviceA;
private $serviceB;
private $param;

public function __construct(A $serviceA, B $serviceB, $param = 0) {
$this->serviceA = $serviceA;
$this->serviceB = $serviceB;
$this->param = $param;
}

public function doSth() {
// ...
}
}

// service definition for container

<service id="my_service" class="Acme\SomeClass">
<argument type="service" id="some_service_a" />
<argument type="service" id="some_service_b" />
<argument>123</argument>
</service>

Call an helper from a service

Symfony isn't magic. Symfony is just PHP. That's the most important thing to remember when working with Symfony.

So if there is no get() method in your class, you can't call the method. In your controller, you extend from a base Controller of the FrameworkBundle. This class does contain such a method, so in a controller you can call this method.

Now, you still want to use the Notification service in your new service. Instead of getting it from the container, let the container inject it in your service when it's creating it. You do this with some service config:

# app/config/services.yml
services:
app.your_service:
class: AppBundle\Some\Class
arguments: ['@Notification'] # <<-- this tells to inject the service

And then adapting this in your class:

class SomeClass
{
private $nofication;

public function __construct(NotificationInterface $notification)
{
$this->notification = $notification;
}
}

There is a lot more to explain about this. See http://symfony.com/doc/current/book/service_container

Symfony2 global functions

In the Symfony2 world, this is clearly belonging to a service. Services are in fact normal classes that are tied to the dependency injection container. You can inject them the dependencies you need. For example, say your class where the function calculate_hash is located is AlgorithmicHelper. The service holds "global" functions. You define your class something like this:

namespace Acme\AcmeBundle\Helper;

// Correct use statements here ...

class AlgorithmicHelper {

private $entityManager;

public function __construct(EntityManager $entityManager) {
$this->entityManager = $entityManager;
}

public function calculate_hash() {
// Do what you need, $this->entityManager holds a reference to your entity manager
}
}

This class then needs to be made aware to symfony dependecy container. For this, you define you service in the app/config/config.yml files by adding a service section like this:

services:
acme.helper.algorithmic:
class: Acme\AcmeBundle\Helper\AlgorithmicHelper
arguments:
entityManager: "@doctrine.orm.entity_manager"

Just below the service, is the service id. It is used to retrieve your service in the controllers for example. After, you specify the class of the service and then, the arguments to pass to the constructor of the class. The @ notation means pass a reference to the service with id doctrine.orm.entity_manager.

Then, in your controller, you do something like this to retrieve the service and used it:

$helper = $this->get('acme.helper.algorithmic');
$helper-> calculate_hash();

Note that the result of the call to $this->get('acme.helper.algorithmic') will always return the same instance of the helper. This means that, by default, service are unique. It is like having a singleton class.

For further details, I invite you to read the Symfony2 book. Check those links also

  1. The service container section from Symfony2 book.
  2. An answer I gave on accesing service outside controllers, here.

Hope it helps.

Regards,

Matt

Symfony2 Dependency Injection / Service Container

Dependency Inction means that you pass objects into a class, instead of initializing it in the class. A Service Container is a class which helps you managing all these services (classes which have dependencies).

Your questions:

Is this the best method?

Yes, except for the namespace.

Should the class be inside a 'Service' directory within the bundle as I have done?

No, it can live in any namespace. You should put it in a logical namespace, such as MyBundle\Logger.

What is the DependencyInjection folder for?

It's meaned for 3 types of classes: Extension, Configuration and Compiler passes.

How call method from service container in config in Symfony?

If getA() and getB() returns object, you can use a factory when configuring your service:

services:
wf.autoload:
class: Scope\WfBundle\WfAutoloadService
arguments: ["@doctrine.orm.entity_manager"]
wf.autoload.getA:
class: A
factory: ["@wf.autoload", getA]

And set the global twig:

twig:
globals:
varA: "@wf.autoload.getA"


Related Topics



Leave a reply



Submit