Dependency Injection in PHP

Dependency Injection in PHP

Tutorial Details
  • Difficulty: Intermediate
  • Completion Time: 15 Minutes

Dependency injection has been a frequent subject of discussion among many corporate developers in the past few years. Many feared that they might sacrifice too much time building their application architecture without doing any real work. In this article, I’ll explain why PHP developers should consider taking advantage of dependency injection, when building large, scalable projects.


What is Dependency Injection?

Before digging into the subject, let’s precisely define what dependency injection is. Let’s imagine that you currently work on a “Question and Answers” website, similar to Stack Overflow. You would more than likely create a class, called Question, which would contain a member of type Author. In ‘ye olden days, programmers would have created the Author object directly in the Question constructor, like this:

class Author {
    private $firstName;
    private $lastName;

    public function __construct($firstName, $lastName) {
        $this->firstName = $firstName;
        $this->lastName = $lastName;
    }

    public function getFirstName() {
        return $this->firstName;
    }

    public function getLastName() {
        return $this->lastName;
    }
}

class Question {
    private $author;
    private $question;
    public function __construct($question, $authorFirstName, $authorLastName) {
        $this->author = new Author($authorFirstName, $authorLastName);
        $this->question = $question;
    }

    public function getAuthor() {
        return $this->author;
    }

    public function getQuestion() {
        return $this->question;
    }
}

While many programmers might call this good code, there are in fact many problems with it:

  • The author’s information passed to the Question constructor has nothing to do inside Question‘s scope. The name of an author should be inside the Author class because it has nothing to do with the question, itself.
  • The Author class is tightly coupled with the Question class. If we add a new parameter to Author‘s constructor, we then have to modify every class where we create an Author object – a tedious and long process, especially in large applications.
  • Unit testing the Question class creates the unwanted behavior of having to test the Author class as well.

Dependency injection alleviates these issues by inserting the dependencies through the dependent class’ constructor (“Constructor Injection”). The result is highly maintainable code, which might look like this:

class Author {
    private $firstName;
    private $lastName;
    
    public function __construct($firstName, $lastName) {
        $this->firstName = $firstName;
        $this->lastName = $lastName;
    }

    public function getFirstName() {
        return $this->firstName;
    }

    public function getLastName() {
        return $this->lastName;
    }
}

class Question {
    private $author;
    private $question;

    public function __construct($question, Author $author) {
        $this->author = $author;
        $this->question = $question;
    }

    public function getAuthor() {
        return $this->author;
    }

    public function getQuestion() {
        return $this->question;
    }
}

Advantages of Dependency Injection

You need to use Dependency Injection for long-term projects.

I have worked on many commercial projects in my career. Some of them are very well written; however, I must say that most of them have considerably poor code quality. I was recently assigned to work on such a code base…

A company requested the application in 2009. The project’s budget was properly planned, but the project manager wanted the application built very quickly to impress his boss. At least, this is what my co-worker told me. Writing an application quickly might sound great to reduce costs, but it also means that the developers jumped into the code without proper planning.

The developers wrote code quickly, creating classes necessary to perform the necessary functionality. The features changed as the project evolved, and because the project was poorly planned (and every class was tightly coupled), the project became difficult to develop.

Currently, it’s difficult to work on this project. Modifying a simple class results in a cascade of other modifications in other classes, because everything is coupled together – resulting in many bugs. Each time something is modified, the developer needs to chase down and fix bugs.

The application is also impossible to unit test, degrading the code’s quality.

Every feature must be manually tested, losing valuable time that could be spent elsewhere. In fact, to reduce the cost of manual testing, we created software to test the infrastructure of the application. Yes, we had to create new software in order to test the actual product.

The company learned that trying to quickly write software resulted in unexpected costs. At first, the company made a lot of money because they charged a lot for it, but after three years, they lost money on this application. The amount of money they pulled in doesn’t cover the continued, high expense of maintenance. They also lost many good, senior developers, who lost any desire to work on the project.

If the application used dependency injection, the developers would have been able to properly unit test the full application, leading to reduced maintenance costs and debugging. The company would have focused on creating new features that last, instead of losing software quality every time that a new feature was introduced. They would also have kept their senior team members and avoided losing money by finding and hiring new employees (which is difficult to begin with in my city).


Getting Started on a Limited Budget

While dependency injection helps assists you in writing better code, it can also require extra time and effort to do it correctly. This can prove to be an issue, if you need working code for a demo.

If all you need is a proof of concept, then I suggest that you don’t waste time with dependency injection and proper architecture.

Jump right in and start coding. You can do things correctly after the project is approved and you have the necessary funding. In fact, once you do have proper funding, throw away your demo and begin from scratch. Otherwise, your application will end up as a spaghetti-code-trash-can.


Messy Start-up Code

So, you’ve begun passing your dependencies in your class constructors, but as the project grows, you end up with many levels of objects that must be created when your application starts. Depending on your application’s size, creating all objects to launch your application can be a very long process and hurt your application’s performance (as well as result in messy code). Here’s an example:

/*
    Please note that the nature of the application is not important here. I only wanted to show how hard-to-maintain/awful such code can be:
*/
$filePath = "/path/to/file";

$fileBuilderFactory = new ConcreteFileBuilderFactory();

$filesXmlBuilderFactory = new ConcreteFilesXmlBuilderFactory($fileBuilderFactory);

$softwaresRetrieverCriteriaBuilderFactory = new ConcreteSoftwaresRetrieverCriteriaBuilderFactory($filesXmlBuilderFactory);

$softwareRetrieverCriteriaBuilderFactory = new ConcreteSoftwaresSoftwareRetrieverCriteriaBuilderFactory($filesXmlBuilderFactory);

$filesJsonBuilderFactory = new ConcreteFilesJsonBuilderFactory($fileBuilderFactory);

$objectBuildderFactory = new ConcreteSoftwaresSoftwareObjectBuilderFactory();

$softwaresSoftwareBuilderFactory = new ConcreteSoftwaresSoftwareBuilderFactory($objectBuildderFactory);

$xmlSoftwareRepository = new XmlSoftwareRepository($softwaresSoftwareBuilderFactory);

$softwaresBuilderFactory = new ConcreteSoftwaresBuilderFactory($xmlSoftwareRepository, $softwareRetrieverCriteriaBuilderFactory, $filesJsonBuilderFactory);

$xmlSoftwaresRepository = new XmlSoftwaresRepository($softwaresBuilderFactory);

$softwareToHashMap = new ConcreteSoftwareToHashMap();

$softwaresToHashMap = new ConcreteSoftwaresToHashMap($softwareToHashMap);

$jsonSoftwaresService = new JsonSoftwaresService($softwaresToHashMap);

$di = new DependencyInjection($softwaresRetrieverCriteriaBuilderFactory, $xmlSoftwaresRepository, $jsonSoftwaresService);

This start-up code is rather small. If you build a large application, your start-up code can become much heavier than this. Needless to say, this results in some difficult to maintain code.

To solve this problem, we need a dependency injection application that reads an XML file and creates all the necessary objects needed to launch the application. The objects would then be serialized and written to a file. The start-up code would then simply read that file and directly create the objects. This makes your start-up code as simple as:

$objectFilePath = "/path/to/serialized/object/file";
$di = unserialize(file_get_contents($objectFilePath));

Open Source Dependency Injection Software

Most companies do not have much budget to create tools, such as a dependency injection framework. You can, however, find many free and open source solutions around the web. Symfony2 uses a very solid DI component that is based on Java Spring. However, I will cover programming a dependency injection solution in the near future, if that interests you. Stay tuned!


PHP Devs and Dependency Injection

I don’t want to generalize, but, due to its popularity, many PHP developers are hobbyists, who love to mix PHP and HTML.

These developers normally don’t plan their project; they just want to write code quickly to “get things done.”

I believe that hiring these types of developers is the worst thing a manager can do. By stressing the importance of dependency injection, you can make these “hackers” disinterested in your company, while, at the same time, enticing good developers to work for you company. In other words, your project will attract good senior developers, which is the most important resource a software development company could acquire!


When to Use Dependency Injection

Dependency injection is most useful, when working on long-term projects.

From my experiences, dependency injection is most useful, when working on long-term projects – projects that are actively developed and maintained over a long period of time. This greatly reduces your costs and attracts the best developers. But, as I mentioned before, if you need a demo application to get a contract or some funding, I’d recommend digging right into the code. If you follow that path, however, be aware that the demo will need to be thrown away after you acquire contract and/or funding.


Story Time!

I love stories about developers who want to do the right thing, but their co-workers want to forego best practices and push a project out as fast as possible. What are your thoughts on dependency injection? An over-complication, or a requirement for any sustainable application?

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • doobdargent

    I agree with the article until the “Messy Start-up Code” chapter.

    Why do you use serialized objects? From what I understand, you’re just hiding the code and make it less maintenable. Did I miss something?

    • Richard

      I think the authors suggesting that you would actually be loading a cached copy of the objects from a serialized file. To build up the cache you would load the objects and configure them in accordance with your XML config file. The advantage being easy configuration but faster loading – once the serialized cache is built.

      • anymous

        no comment

    • anymous

      yes

      • anymous

        no

    • anymous

      i dont agree

      • anymous

        still got any comment

    • Nat4an

      serializing code makes it more secure and easier to maintain.

  • showcasefloyd

    I wish there were better examples in this article. I get the authors argument for why you should use, it but the one example doesn’t tell me much.

    • benplum

      Bump. Looking for a more real world example.

      • Matthieu

        Here is a simple and clear example from PHP-DI (http://mnapoli.github.com/PHP-DI/), a dependency injection library.


        class Foo {
        /**
        * @Inject
        * @var Bar
        */
        private $bar;
        }

        Here, an instance of class “Bar” is injected into “Foo”. You don’t need to create a new instance of Bar in Foo manually, it’s injected automatically.

      • Matthieu

        The linked is messed up, here it is : http://mnapoli.github.com/PHP-DI/

    • http://twitter.com/emerazea emerazea

      Similarly, from the one example, I don’t think I fully understood what dependencies are. I say this because it seemed like an easy thing to fix, but obviously they aren’t if this is something ‘worth paying attention to only in large projects’ rather than just making a slight change in coding habits consistently as a best practice.

      This was the only difference…

      public function __construct($question, $authorFirstName, $authorLastName) {

      $this->author = new Author($authorFirstName, $authorLastName);

      }

      public function __construct($question, Author $author) {

      $this->author = $author;

      }

      So… seems easy enough.
      I’m quite new to php, though. I get what having something depend on something else is. I just don’t know that I’d know how to write it better at this stage without being shown. As is, this post came off less instructive and more like a reminder notice to already-elite (but sloppy/lazy/time-constrained) php programmers.

      • http://felipe.lv/ Felipe Lavín

        Yup, I understand the desire to let the story do the teaching, but in this case the story it’s vague and the teaching too general… I missed a clear definition of DI, more examples and more concrete info

    • Matt

      Following your comment, I thought I’d write an example based on a real-life example, you can read it here: http://en.mnapoli.fr/introduction-dependency-injection-with-real-life-example/

    • Benjamin VanEvery

      My main issue with most dependency injection frameworks is that they require configuration outside active code. This seems counterintuitive when you generally know exactly which class you need and want to create it on the spot. The dilemma is that you need to inject other mock or stub classes for testing, so you have to avoid constructors. Using annotation based frameworks or the factory based framework described here leads you to a severed codebase in which the casual reader doesn’t really know how, or when, objects are being created. This just feels like an unnecessary level of abstraction and I really struggle to see how it is advantageous.

      At my company we use a system called Diesel, http://asheepapart.blogspot.com/2012/07/php-dependency-injection-part-2.html, which injects your objects on the spot based on what you ask for. There is no behind the scenes XML file or other type of configuration file. It’s straightforward and allows you to transparently inject stub or mock objects for testing.

      I’m curious what other people think about it.

  • Zach

    This is exactly why we have frameworks is to avoid all this… even a simple auto loader with a router can go along way to avoid messy boot loaders and classes that have to instantiate other objects. This article reminds me of the Singleton pattern an how to layout your class objects. the most common practice you’ll see in pretty much all base frameworks is a signal object that all classes extend allowing the developer to follow the tree of “this”

  • http://www.codedevelopr.com/ Jason Davis

    I believe Dependency Injection is good practice to use but I am not sure I agree 100% with the XML file to store serialized objects. I think there are better performing methods to do Dependency Injection and I will try to go over some of them on http://www.codedevelopr.com

  • http://www.facebook.com/people/Eli-McMakin/1436543193 Eli McMakin

    When did DI become popular in PHP? I have seen people passing objects as a param with the __constructor, but never knew what it was called. has this technique been around for more than 4 yrs?

    • http://www.kksmith.me/ K.K.Smith

      I agree. I’m kind of new-ish to PHP myself, but this seems to be solving a problem that I just haven’t seen much.

      It seems a no-brainer that you would instantiate objects before passing them as arguments, as opposed to creating them inside of another object.

  • mattsah

    There are Pros and Cons as with anything. There are some relatively valid points made in this article, which is obviously not in favor of DI: http://www.tonymarston.net/php-mysql/dependency-injection-is-evil.html. Additionally, as most people know around here, I’m rather dismayed by the large variety of methods in which it’s occurring in the PHP community. FLOW3 and Laravel4 both introduced annotations as a method of facilitating this… I have no incentive at the moment to check if they use the same annotation syntax, but I will make an assumption they don’t. There’s also a number of various DI container type classes out there, all with varying featuresets that promote everything from only the most simple DI requirements to the most complex — (I have still yet to see one that allows you to enforce interface compliance).

    In short, a lot of newcomers are getting confused, a lot of methodologies are emerging, and a lot of the community is fragmenting over something which offers very little in terms of maintainability when compared to other practices. This movement is heavily tied to the TDD crowd and its only sole defensible argument has been “it’s difficult to test a ‘pure’ unit with hard coded dependencies.”

    I actually read a thread somewhere where someone was going off on another guy for injecting the container and essentially breaking into a service locator pattern and screaming about how it’s an anti-pattern and all this…

    My culutral and historical take is as follows: Ruby (a severely object oriented language with high meta-programmability) got its rails. PHP community saw it getting popular, so jumped on the MVC bandwagon. Ruby community got filled up with a lot of younger hipster types who were looking to older and actually skilled OO programmers who came from other languages to Ruby for various valid reasons. Older guys said, “here’s some good principles of OO.” Young Ruby hipsters took these tips as the word of God, pushed them to an extreme, and PHP has been playing catch up to this. The last 5 – 6 years of the PHP community’s development has essentially been following whatever the latest bandwagon of the Ruby community has been.

    This gets made about 1000 times worse because of all the emphasis now on design patterns. If I’m not mistaken Laravel 4 is actually and attempt to implement every design pattern which has not flagged as an anti-pattern somewhere in a single framework, regardless of whether it’s actually useful or serves a need.

    For my extended thoughts on more technical aspects: http://scriptogr.am/mattsah/post/dependencies-in-php

    I’m seriously considering Dart to escape this madness.

    • David Welch

      Interesting thoughts and articles. Though I’d disagree on your history lesson. I’m definitely not a hipster (my roots are actually in PHP and Java EE) but I generally try to work with every emerging language / platform and I see it a bit different.

      Besides my core skill set, I’ve worked with Python / Django, Clojure, Scala, Ruby (Rails / Sinatra) and deployed apps in Node & C# / .Net. Working across all these different technologies & digging into their background has made me realize one thing: they *all* feed off each other.

      There’s constant feedback from the “cool” or “best practice” principles that are circulating and jumping from one camp to the next. So it makes sense that other camps adopt the new emerging principles, but unfortunately they don’t always fit the programming paradigm. I could very much see DI being somewhat of a mismatch for PHP, especially considering the way classes are (usually) dynamically resolved

      That being said, hard coded dependencies is far worse than the DI abstraction IMO.

      • mattsah

        @google-ae8882941b8598095931802daf4651f5:disqus

        You hit the nail on the head with this, “I could very much see DI being somewhat of a mismatch for PHP, especially considering the way classes are (usually) dynamically resolved.” Not so much in saying that it is a mismatch (cause I don’t think that’s what you were absolutely saying), but simply in the fact that it “could” be.

        The more important point I was making with regards to history and culture is that PHP has been very quick to adapt things which make more sense in other languages as it has “grown up” to become object oriented. Building 800 MVC frameworks cause of the rise of Rails translated fine in my opinion, and gives us the lovely variety we have today (something for everyone)… however, looking at DI in other languages which we’re borrowing a lot of OOP principles from (namely Java) does not always translate well.

        I frankly have never felt hard-coded dependencies were “far worse than the DI abstraction.” Like most things there are pros and cons to both. I will take hard-coded dependencies over FLOW3 style aspect oriented programming any day of the week, if for no other reason than clarity. Thankfully there are creative solutions to the problems that both cause… so long as people are willing to work towards them and use them (most aren’t).

  • conarw

    Well said, I love DI. Laravel has a great setup for using IoC and DI IF you have the luxury of starting with a fresh code base.

    I am constantly pushed aside when trying to integrate things like this in my current situation. Most don’t know or understand what it is, or its benefits, but apparently are knowledgeable enough to shun it as a waste of time, or unnecessary. Whenever dependency injection, testing, documentation and maintainable code is even mentioned I hear the usual responses: “That’s a waste of time”; “It’s impossible to integrate it into our current system”; “You just don’t understand”; “It doesn’t work with our business model”.

    What I actually hear though is “I don’t feel like learning anything new, I don’t feel like putting more work than needed in, and I would rather just do it my way”. A bunch of excuses really. I would like to meet the person who actually spent time to learn about this, and still had bad things to say about it. I would be extremely interested to hear the reasoning. Like you said, they would just rather hack their way through whatever problem may come, rather than plan for them.

    Difficult to change the direction of an existing project… probably. Worth it… definitely.

    I agree with you in saying that a process involving these types of practices will save significant amounts of time, money, and resources throughout the lifetime of the software. As well as develop software that welcomes senior developers, makes training for new developers easier, and allows for easy and clean upgrades/fixes to the software.

    What solution are you planning on covering in the future?

  • kd

    I think the ‘hiring’ hobbyist section of your article is pretty arrogant, everyone has to learn somewhere maybe a reasonable philosophy would be that a mentoring environment would help teach best practices…as they seem to be changing regularly….I’ll stop there.

  • http://rommelxcastro.com/ Rommel Castro A.

    i realluy liked this article, willing to learn more about it

  • jaspersam

    wow good info

  • Nigel

    That “don’t hire hobbyist” remark is not very insightful. Hiring these people is the only way to help them become better, and the PHP community because of it. Entry level positions exist for a reason. They are the majority of PHP developers and deeper understanding of concepts like dependency injection is only going to come by experience. Experience they’ll never get if they don’t get the chance to learn from other people.

    Interview them thoroughly and sift out the really bad ones. If you get someone with a good understand of basic php and who knows they’ve still got a lot to learn(don’t we all?), then you’ve good a good person. And there’s hope for those people who’re willing to learn.

    But the whole point is the learning: how are they going to learn if they’re not allowed in to environments where they *can* learn. People need jobs now, not after 5 years of buying books off unemployment money.

    • http://www.jeffrey-way.com Jeffrey Way

      I agree, but I think the author was referring more to hobbyists, who maybe don’t have any real ambition to be a high-level developer.

    • James Fair

      I completely agree with you Nigel. Many great programmers that have succeed in landing great careers or created million dollar companies like Mark Zuckerberg started as hobbyist !

  • Elze

    I agree with the previous comments, the tone of voice regarding new developers is not very insightful. Studies have shown that a team of only senior developers don’t work, you need the right mix. But back on topic, dependency injection can be very usefull if used correctly. It’s usage is not without controversee and discussion, same goes with inversion of control.

  • alex

    This article really deserves more love. This is a mandatory read for project managers, especially young ones.

    Another good discussion would be about when should a business / project manager let go of the “if it ain’t broke don’t fix it” mentality regarding old code and embrace things like dependency injection?

  • http://www.facebook.com/galdikas Vytautas Galdikas

    Can someone clarify this…

    So basically all he means is that instead of creating new instances of classes in other classes, instead we should pass around class that was already instantiated as an argument to other class constructor?

    • Jukk

      Exactly. I vote for this comment as a replacement for all these smart articles about DI.

    • conarw

      No, if I understood his intent correctly, he was just providing a simple example of “constructor injection” to prove a point. Full scale dependency injection can get a little complicated for a tutorial like this, being as they must introduce several other topics at the same time.

      I think this was just a teaser article to get across the idea that without dependency injection, you have many limitations, however with dependency injection you have many options. If you are hardcoding dependencies into your classes, any changes to those dependencies (upgrades, bug fixes, etc) will require you to search for every place that calls that dependency, and update how it was called. Anything short of perfection in that refactor causes bugs.

      The thing that this example does not show very well, is how it can save you both time and frustration. For instance, if you have the following:


      class Another {}
      class Third {}

      class Something {
      public function __construct( Another $another, Third $third ){
      $this->another = $another;
      $this->third = $third;
      }
      }

      $another = new Another;
      $third = new Third;
      $third->someConfig = '123';
      $third->anotherConfig = '456';

      $something = new Something( $another, $third );

      We manually created instances of the dependencies, and placed them into the constructor of the parent class, removing the need to build them out in the constructor. While it may seem that there is no need or benefit to displace this functionality, try and do unit testing without this and you will quickly see the frustration.

      –note: even if you stop right there, you have already improved your app with better code quality, however there is much more that can be done.

      Now that you are setup this way, you have several new tools available to make this better:

      You can use inversion-of-control to actually instantiate the dependencies, which will help you be able to do things such as pass configs and setups in only one place, instead of repeating that work for every occurrence. You can also have different variations of instantiation done this way.

      You can also use reflection so that it is not even necessary to pass in the dependencies at all, instead, reflection will take a look and see that there are 2 dependencies needed to create this class, and will get and load them for you automatically, maybe even checking your IoC container first to see if there is a process for creating that object.

      There are many more theories and methods to use here, this is only the surface.

      There is a joke:
      4 hours of programming will save you 1 hour of planning.

      It may seem easier to hack in a solution in the most direct way, but the benefits that come from a little bit of planning and organization, are ones that will last the entire lifetime of the product. Your developers will also have a much easier time maintaining, and upgrading the product, and be happier and more loyal for it. Maybe he should have called the article “Dependency injection, the gift that keeps giving”. If you have never tried any of these methods before, it is going to be a weird road in learning it, and implementing it will seem like a ton of work, but I assure you it is not, and that it is worth it!

    • conarw

      No, if I understood his intent correctly, he was just providing a simple example of “constructor injection” to prove a point. Full scale dependency injection can get a little complicated for a tutorial like this, being as they must introduce several other topics at the same time.

      I think this was just a teaser article to get across the idea that without dependency injection, you have many limitations, however with dependency injection you have many options. If you are hardcoding dependencies into your classes, any changes to those dependencies (upgrades, bug fixes, etc) will require you to search for every place that calls that dependency, and update how it was called. Anything short of perfection in that refactor causes bugs.

      The thing that this example does not show very well, is how it can save you both time and frustration. For instance, if you have the following:


      class Another {}
      class Third {}

      class Something {
      public function __construct( Another $another, Third $third ){
      $this->another = $another;
      $this->third = $third;
      }
      }

      $another = new Another;
      $third = new Third;
      $third->someConfig = '123';
      $third->anotherConfig = '456';

      $something = new Something( $another, $third );

      We manually created instances of the dependencies, and placed them into the constructor of the parent class, removing the need to build them out in the constructor. While it may seem that there is no need or benefit to displace this functionality, try and do unit testing without this and you will quickly see the frustration.

      –note: even if you stop right there, you have already improved your app with better code quality, however there is much more that can be done.

      Now that you are setup this way, you have several new tools available to make this better:

      You can use inversion-of-control to actually instantiate the dependencies, which will help you be able to do things such as pass configs and setups in only one place, instead of repeating that work for every occurrence. You can also have different variations of instantiation done this way.

      You can also use reflection so that it is not even necessary to pass in the dependencies at all, instead, reflection will take a look and see that there are 2 dependencies needed to create this class, and will get and load them for you automatically, maybe even checking your IoC container first to see if there is a process for creating that object.

      There are many more theories and methods to use here, this is only the surface.

      There is a joke:
      4 hours of programming will save you 1 hour of planning.

      It may seem easier to hack in a solution in the most direct way, but the benefits that come from a little bit of planning and organization, are ones that will last the entire lifetime of the product. Your developers will also have a much easier time maintaining, and upgrading the product, and be happier and more loyal for it. Maybe he should have called the article “Dependency injection, the gift that keeps giving”. If you have never tried any of these methods before, it is going to be a weird road in learning it, and implementing it will seem like a ton of work, but I assure you it is not, and that it is worth it!

    • Matthieu

      No, not necessarily.

      Dependency injection means that instead of Class1 fetching its dependencies itself, it will get them from someone else: it may get its dependencies in the constructor, or via other ways. That way, you can control the dependencies that Class1 will use and change them at will without changing any line of code in Class1.

      For example, an other way of injecting a dependency is with annotations:

      class Foo {
      /**
      * @Inject
      * @var Bar
      */
      private $bar;
      }

      Here, an instance of class “Bar” is injected into “Foo”. This is possible with frameworks or library, here it’s an example for PHP-DI (http://mnapoli.github.com/PHP-DI/).

  • Patkos Csaba

    I’ve seen and I use injection like below many times, especially when I do TDD, the tests kind of require this kind of trick to make things easier. This is the code example:

    class SomeClass {
    private $theOtherObject;
    __construct( $injectedObject = NULL ) {
    $this->theOtherObject = $injectedObject ? : new TheOtherObject();
    }
    }

    This simple trick allows tests (or any other client for that matter) to inject the dependency and also offers a default behavior by creating the object if not provided.

  • Guðjón Jónsson

    You could have mentioned also that a clever way to use Dependency Injection is to use it with interfaces, where the constructor of some class takes an interface, which classes implement in a different way.

  • asdfasf

    asdfsadf
    asfdasdf

  • Prashant

    Very well written tutorial, and some useful information. Thanks!

  • Rami Tayba

    Nice Article, waiting the next.

  • PaoloUmali

    I may not be an expert but the moment I read this, ‘The author’s information passed to the Question constructor has nothing to do inside Question‘s scope. The name of an author should be inside the Author class because it has nothing to do with the question, itself.’, I replied here then close the tab.