2

given a class:

class Container
{
    public function getServiceX()
    {
         create and return it
    }

    public function setServiceX ($obj)
    {
    }
}

This stores an instance of an object. You can regard it as a factory. In action:

public function addTitle()
{
    Container::getServiceX()->doIt();
}

they say its bad, because its "global". But objects can be changed so it satisfies the DI - but hurt LoD. If thats bad, what is the good solution? How to make sure that a class reaches the serviceX?

John Smith
  • 6,129
  • 12
  • 68
  • 123
  • 5
    Usually globals are seen as bad because people don't know how to treat them properly. However, using a class as a singleton instance can be perfecly valid for some use cases. My question is more... who is they? – Tschallacka Sep 07 '15 at 14:44

2 Answers2

4

Essentially this is a service locator or service factory. You may even call it a dependency injection container. That in itself is perfectly fine. It's great in fact. The problem with it is that you call it statically! You should be injecting your dependency injection container into your class:

class Foo {

    protected $container;

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

    public function addTitle() {
        $this->container->getServiceX()->doIt();
    }

}

There, now you're fully dependency injected and decoupled.

With a statically coupled call, you can still get into situations you were trying to avoid with a dependency injection container in the first place. What if you need to inject one class with service X and a second class with a slightly differently configured instance of service X, but you're statically calling the same container which can only hold one copy of service X? You're solving this by decoupling the static call to your container and allowing a differently configured container to be injected.

Marco Demaio
  • 33,578
  • 33
  • 128
  • 159
deceze
  • 510,633
  • 85
  • 743
  • 889
  • 1
    @John You may be interested in this: [How Not To Kill Your Testability Using Statics](http://kunststube.net/static/) – deceze Sep 07 '15 at 14:51
  • of course, but why to even instantize this Container? No need an instance of it. – John Smith Sep 07 '15 at 14:52
  • 2
    Because that's exactly what OOP is all about. Because maybe *today* you cannot see any need for having *two different instances* of `Container` at the same time. But tomorrow you may find yourself in the situation I describe in my answer and wish you could have two separate instances of your container. – deceze Sep 07 '15 at 14:53
  • About the only time I'd argue *for* a Singleton pattern (which never allows 2 instances of the object) would be for a Session management object ... since you're never going to have 2 instances of the user's Session. – CD001 Sep 07 '15 at 14:57
  • One of the great things about PHP is that it is designed to be stateless and shared nothing. It's memory is discarded after the job's done. It is obviously possible to have a PHP application that runs forever, but that is a very uncommon scenario. Injecting dependencies via the constructor is bad practice, because you'll be instantiating objects that you may not need - which hurts performance. Unless you make your controllers so that all methods require the same dependencies. A workaround is to have proxy objects, but still those proxy objects need to be made. Service Locator is better for PHP – frodeborli Sep 16 '19 at 09:45
1

Using global containter makes it harder to test the code. Also you don't have much control of object state. It is against SOLID.

Dependency injection is a lot better way.

Check this link What's the difference between the Dependency Injection and Service Locator patterns?

While using dependency injection you can easily mockup objects and make them easy to test. You don't pass or create them staticly but you pass them for example via constructor of the service.

You can also check how Symfony2 developers did it: http://symfony.com/doc/current/components/dependency_injection/index.html

Community
  • 1
  • 1
Robert
  • 19,800
  • 5
  • 55
  • 85