Dependency Injection Question

I think I have the hang of DI. Am I right in saying that you can inject in a function like this:

public function foo(Bar $bar) {}

^ This could be a constructor also.

I haven’t tried it yet but I assume you can do:

private Bar $bar;

Is that the gist of it?

My question is, how do you do dependency injection if you are creating an anonymous object? (Not sure if that is the right name for it)

public function foo() {

    return new Bar();

}

How do you inject in that situation—or is that classed as injection?

Yes, to your first example, but I’d take it further and do

public function foo(IBar $bar) {}

I like to use Interfaces instead purely because you can inject various implementations that abide by the contract of the interface giving you greater flexibility.

I’m not sure what you are getting at here. Are you presuming you’d have a private variable within your class? Or are you creating that to send to your class? If the former, I’d again go with IBar to keep the flexibility and then the constructor would receive IBar as a parameter and assign it to the private variable.

No, you are effectively making your class that contains foo() dependent on Bar now. This is not DI. This makes it nearly impossible to mock/test or process a different class that implements the same contract because you are forcing Bar to be used.

No, that would be static typing, like in Java or C. PHP is dynamically typed, so you can’t specify the type of a variable.

Thanks, so in that instance, how do I make the class dependent on the class that has function foo()?

public function foo(Bar $bar) {

    return new Bar();

}

That seems odd to me. I do find that this circumstance does come up every now and then.

Let’s go with a broader more specific example that is commonly used: Animals Speak

<?php
interface IAnimal
{
	function Speak();
	function Eat();
	function LastTimeAte();
}

abstract class Animal implements IAnimal
{
	protected $lastTimeAte;
	public function Speak()
	{
		throw new NotImplementedException();
	}
	
	public function Eat()
	{
		$this->lastTimeAte = new DateTime();
	}
	
	public function LastTimeAte()
	{
		return $this->lastTimeAte;
	}
}

class Cat extends Animal
{
	public function Speak()
	{
		echo "Meow!";
	}
}

class Dog extends Animal
{
	public function Speak()
	{
		echo "Woof!";
	}
}

class Vet
{
	private $animal;
	public function __construct(IAnimal $animal)
	{
		$this->animal = $animal;
	}
	
	public function Exam()
	{
		if ($this->animal->LastTimeAte() < new DateTime('1 week ago'))
		{
			$this->animal->Eat();
		}
	}
}

Now I can send either the Dog or the Cat to the Vet for an Exam. Vet doesn’t need to know which one it is, it just needed to know that it implemented IAnimal.

That’s a great example, thanks. But let me explain where I’m coming from.

Example (simplified, not real code):

class Database {

    // Other database stuff going on here

    public function query($query) {

        $result = mysqli_query($this->link, $query);

        return new DatabaseResult($result);

    }

}

$result = $database->query("SELECT * FROM foo");

I can’t create the result object until after the query so there is nothing to send to the database object. Can you not do DI under these circumstances?

Let me ask this, what is the purpose of DatabaseResult?

As an aside, I’d break up your query into two methods (query and fetch, and potentially fetchAll).

class Database { 

     private $result;

    // Other database stuff going on here 

    public function query($query) { 

        $this->result = mysqli_query($this->link, $query); 
        return $this; // so I can chain other methods
        //return new DatabaseResult($result); 

    } 

    public function fetch(IDatabaseResult $databaseResult)
    {
        return $databaseResult->Process($this->result);
    }

    public function fetchAll(IDatabaseResult $databaseResult)
    {
        return $databaseResult->ProcessAll($this->result);
    }

} 

$result = $database->query("SELECT * FROM foo")->fetch(new DatabaseResult());
$result = $database->query("SELECT * FROM foo")->fetchAll(new DatabaseResultCollection()); 

Cpradio, would DatabaseResult not be an instance of a ‘newable’ (see: http://misko.hevery.com/2008/09/30/to-new-or-not-to-new/) - a class that couldn’t be retrieved from an injection container because it’s an entity and holds state?

Not necessarily in the way I used it, but yes, it could be. Partially, which is why I asked what its’ purpose is. If it’s purpose is to store the information from the query and just relay that back (like a data transfer object), then yes, I’d agree it doesn’t need DI.

However, if the results could be parsed/processed differently based on application decisions, then it would benefit from DI.

In this case, I think you would need a factory class.

class DatabaseResult
{
    /*
    No changes needed here.
    This class can be ignorant of the larger outside world.
    */
}

class DatabaseResultFactory
{
    /*
    This class's sole job is to create DatabaseResult objects.
    It knows about the DatabaseResult class, but is otherwise ignorant of the larger outside world.
    */
    
    public function __construct()
    {
        /*
        Pass in any settings or information needed to create DatabaseResult objects.
        */
    }
    
    public function create($queryResult)
    {
        return new DatabaseResult($queryResult);
    }
}

class Database
{
    /*
    The database is injected with a DatabaseResultFactory.
    */
    
    private $databaseResultFactory;
    
    public function __construct($databaseResultFactory)
    {
        $this->databaseResultFactory = $databaseResultFactory;
    }
    
    public function query($query)
    {
        $result = mysqli_query($this->link, $query);

        return $this->databaseResultFactory->create($result);
    }
}

For a small application, this will probably seem like overkill. But for large applications, it becomes critical that significant code changes nonetheless have a small impact on the overall system. Consider, for example, if one day we decide to swap out DatabaseResult for an EnhancedDatabaseResult. In your old code, you would have had to scrub your codebase to remove any use of DatabaseResult. But in this new code, we would make just one change in one place: we would inject Database with an EnhancedDatabaseResultFactory object instead of DatabaseResultFactory, and everything else would continue to work just like it did before.

We can still make at least one more improvement. PHP is of course a loosely typed language, so we can pass any object to the Database constructor, and as long as that object has a create method, it will work. We can formalize that requirement by requiring an interface. (cpradio mentioned this earlier.)

interface DatabaseResultFactoryInterface
{
    public function create($queryResult);
}

class DatabaseResultFactory implements DatabaseResultFactoryInterface
{
    /* ... */
}

class Database
{
    public function __construct(DatabaseResultFactoryInterface $databaseResultFactory)
    {
        /*
        By requiring an interface, we ensure that whatever object that's passed in will have implemented a create method.
        */
    }
}

That’s actually a really good example. Much more refine than mine and I was being too focused on DI and didn’t look beyond it.