user1517081
user1517081

Reputation: 965

How to properly inject dependencies in PHP

I'm having some issues with dependency injection that I'd like to clearify. The first thing to mention is a dependency injection container (DIC) I implemented, which is capable of registering and resolving dependencies through constructors using ReflectionClass.

$container = new DiC;
$container->register('session', 'CSession');
$container->register('response', 'CResponse');
$container->register('model', 'CSomeModel');
$container->register('view', 'CSomeView');
$container->register('controller', 'CSomeController');

A dependent controller:

class CSomeController extends CController
{
  public function __construct(CSomeModel $model, CSomeView $view)
  {
    // assign arguments here
  }
}

Now the controller can be instantiated through DIC:

$controller = $container->resolve('controller');

I like this approach because it is automated and descriptive, however class CController depends on specific classes CSomeModel, CSomeView which is bad. MVC triads should be instantiated independently - I cannot pass COtherView to CSomeController for example.

My second guess is to inject the DIC:

class CSomeController extends CController
{
  public function __construct(DiC $dic)
  {
    // resolve dependencies through $dic
  }
}

This one makes DiC object global, many people argue this is not the way to implement DI.

Is there a third way that eliminates the weaknesses from both approaches?

Upvotes: 3

Views: 410

Answers (2)

EmeraldD.
EmeraldD.

Reputation: 150

If your looking for "auto-wiring", switch to Interfaces and implement your concrete Model/View/etc. classes against that interface. That way you could use reflection to pair up both sides.

It would also make sense to have a mechanism for explicitly specifying dependencies at the container level.

Upvotes: 1

user1655741
user1655741

Reputation:

I think both approaches are relevant. In case you want to be more flexible in the first approach you could change the constructor to have a parent class as a dependency. Then every object that inherits from that parent class could be injected. I.e.

class CSomeModel extends AbstractCModel {}
class CSomeOtherModel extends AbstractCModel {}

public function __construct(AbstractCModel $model, AbstractCView $view) {}

The second approach is suitable if you need to access factories. I.e. if you need to access multiple instances of the same object.

Upvotes: 1

Related Questions