Jump to content

Recommended Posts

I am trying to understand when, why, and how to use Dependency Injection.  I came up with the following hypothetical script (sorry Jacques, but there is no real script yet).  If my script is totally off base, please advise.  How should I apply Dependency Injection to it?  After I understand how, will also be looking at when and why.  Thank you

<?php
class Container {
    protected $registry = array();
 
    public function __set($name, $resolver)
    {
        $this->registry[$name] = $resolver;
    }
 
    public function __get($name)
    {
        return $this->registry[$name]();
    }

    // What else should be in the container?
}
<?php
class MyClass {
    public function __construct($container)
    {
        // What should be done here?
        echo('MyClass::__construct');
        var_dump($container);
    }
 
    public function foo($name)
    {
        // How do I access the container?
    }
}
<?php
$c = new Container;

$c->pdo = function() {
  $pdo = new stdClass();  //This is a fictional PDO object
  $pdo->foo='foo for pdo';
  // Do anything else...
  return $pdo;
};
 
$c->bla = function() {
  $bla = new stdClass();
  $bla->foo='foo for bla';
  // Do anything else...
  return $bla;
};

$pdo = $c->pdo; // How do I pass arguments to each?
var_dump($pdo);

$bla = $c->bla;
var_dump($pdo);

$pdo = $c->pdo; //How do I prevent creating a new PDO object, and instead use the existing?

//$bad=$c->bad; //Will cause error because not defined
//$c->bad='BAD';
//$bad=$c->bad; //Will cause error because not a function


$myObject=new MyClass($c);  //???
Link to comment
https://forums.phpfreaks.com/topic/302073-understanding-dependency-injection/
Share on other sites

If you're trying to understand how the container object (which provides access to your application objects) works, I'd suggest just spending some time looking at how Pimple does it. It is pretty basic and shouldn't take too long to grasp.

 

The basic idea of the container is two parts: Configuring how objects are created and providing access to object instances.

 

In Pimple both of these are provided by means of the ArrayAccess interface and it's offsetSet and offsetGet methods. You configure an object by assigning a closure to a given key in the container. This closure function handles creating the object instance and returns it for pimple to store and provide to anything that needs it.

 

To obtain an object instance you just read the same key. When attempting to read the key Pimple will first check if the instance has already been created. If so it will return the existing instance. If not it will execute the closure to obtain an instance then mark it as having already been created so future reads won't try and re-create it.

 

Other container implementations may work differently and may provide more features but the overall goal is the same.

 

 

As for why you would want to use Dependency Injection and a container object, it allows you to keep the details of how a particular object is created (generally part of implementation details) separate from code that needs to make use of that object. It also lets you centralize the construction of those objects so if you need to make a change to you can do so in only one place rather than having to find all the places where you use it. Since things are generally defined in the container to only be constructed once it also means that you don't end up with a bunch of duplicate objects when multiple parts of your application all need access to the same object.

 

For example with your database connection you could switch from using PDO directly to using a class that extends PDO and provides extra helper methods easily by defining it in the container then injecting instances of it into your object objects. Likewise if you wanted to change from say MySQL to Sqlite you could do so by just changing the container definition, provided your other code doesn't rely on any mysql-specific queries.

 

Being able to switch to an alternate but compatible implementation can make testing a lot easier. When you create and run unit tests you have a special testing container that creates Mock versions of your dependencies such as an instance of PDO that always throws an error when trying to run a query or that returns specific results for a given query.

If you're trying to understand how the container object (which provides access to your application objects) works, I'd suggest just spending some time looking at how Pimple does it. It is pretty basic and shouldn't take too long to grasp.

 

 

Wow, is that all there is to Pimple?!? I had assumed I would not see the design pattern through the bloated script, and thus started writing my own.  I will spend a little time going over it, and post questions if necessary.  Thank you Kicken for your help.  Michael

This series of articles about DI was written by Fabien Potencier, who is the originator of the Symfony frameworks(s). I highly recommend reading through it prior to making a thread on the subject here.

 

What I got out of Part 1.....

 

Don't have a class create an object.  Instead, create all the objects at the top, and inject them into the appropriate classes via the constructor when required or with a setter if they are option.

 

While I see the value sometimes doing so, I am having a hard time embracing it across the board.  How absolute is this?

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.