Jump to content

Dependency Injection, trying to understand it...


MasterACE14

Recommended Posts

Good day everyone,

 

I've read a few articles on PHP Dependency Injection, downloaded a copy of Phemto and looked at the guts of it. Now reading through for the documentation for Symfony.

 

Symfony Documentation

 

class Container
{
  protected $parameters = array();

  public function __construct(array $parameters = array())
  {
    $this->parameters = $parameters;
  }

  public function getMailTransport()
  {
    return new Zend_Mail_Transport_Smtp('smtp.gmail.com', array(
      'auth'     => 'login',
      'username' => $this->parameters['mailer.username'],
      'password' => $this->parameters['mailer.password'],
      'ssl'      => 'ssl',
      'port'     => 465,
    ));
  }

  public function getMailer()
  {
    $mailer = new Zend_Mail();
    $mailer->setDefaultTransport($this->getMailTransport());

    return $mailer;
  }
}

It is now easy to change the Google username and password by passing some parameters to the container constructor:

$container = new Container(array(
  'mailer.username' => 'foo',
  'mailer.password' => 'bar',
));
$mailer = $container->getMailer();

 

I understand how the parameters work and why that's passed to the container class. But with their example I'm lost with getMailTransport() and getMailer().

 

Or am I making it out to be more complex than it is?

 

Is getMailTransport() simply setting the configurations for the Zend_Mail() class?

I understand getMailer() is returning an instance of that class. Does this mean every class I wish to use will need to have a 'getClassName()' method to return an instance of that class and a respective 'getClassConfig()' method for the configurations, whether they're passed via parameters or not?

 

Any help, understanding and guidance is appreciated.

 

Thank you kindly,

Ace

Link to comment
Share on other sites

DI is nothing new, it's just a name for something that exists since there are 3rd generation programming languages. The DI in your example is the array you pass in, and the mailTransport you pass into Zend_Mail.

 

I could be wrong though, DI doesn't have that much shine, and anything that doesn't shine enough, I'm not interested in.

Link to comment
Share on other sites

Is getMailTransport() simply setting the configurations for the Zend_Mail() class?

 

Yes.  With the way it's used, that method really should be private.  That would probably make it more clear as to its intent.

 

I understand getMailer() is returning an instance of that class. Does this mean every class I wish to use will need to have a 'getClassName()' method to return an instance of that class and a respective 'getClassConfig()' method for the configurations, whether they're passed via parameters or not?

 

Generally speaking, most likely.  A DI/Ioc container has two jobs:

 

1. To wire up the dependency for an object with that object

2. To return that wired up object

 

Now, you may not have to do something as robust as what that example showed.  For example, if you had an object which needed a database:

 

class DBContainer
{
   private $db;

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

   public function getObjectThatNeedsDB()
   {
      $obj = new ObjectThatNeedsDB($this->db);
   }
}

 

Obviously, a canned example.

 

Really, though, the example given by Symfony misses one key component - DI works best when dealing with interfaces (the actual language construct).  That allows one to keep the DI definition the same while being able to change the underlying functionality of one, or both, of the components.  An example would be a MVC controller which needed to access a repository:

 

class BlogController extends Controller
{
   private $repo;

   public __construct(IRepository $repo)
   {
      $this->repo = $repo;
   }

   // ...
}

class Container
{
   public function getController()
   {
      return new Controller($concreteRepo); // <-- all controllers are derived from an abstract base class - assumes only one repository is needed
   }
}

 

If you needed to do some unit testing, or something else along those lines, you could then substitute $concreteRepo for, say, $testRepo without having to take a hatchet to your code.

 

Hope this helps.

Link to comment
Share on other sites

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.