Dependency Injection

Dependency Injection

Dependency injection is a design pattern which allows you to inject your dependencies into a class, rather than have them loaded from within that class. This blog post on PHP dependency injection will be an example based post without too much commentary from me.

 

Typically when we write our classes they require functionality from other classes. One way of achieving this is to include and load a new instance of the dependency within our class. Another possibility is that you include all the functionality in one class, but that limits your scope to expand how the functionality is actually implemented in the future.

 

Lets take a look at one contrived example without PHP’s dependency injection:

 

<?php

class Log()
{
    public function log($message)
    {
        if( $message == "" )
        {
            return;
        }
        
        $message = date("Y-m-d H:i:s")." - ".$message."rn";

        file_put_contents("./messages.log", $message, FILE_APPEND);        
    }

}


// do some stuff

$oLog = new Log();

$oLog->Log("all done!");

?>

 

That’s all good and well, and it works. But what if you wanted to store the actual log as a file but someone else using the Log class wanted to store the messages in a database? You could write multiple log files, or worse still you could have multiple function calls in your Log class, eg:

 

<?php

class Log()
{
    public function logFile($message)
    {
        ... some code here...
    }
    
    public function logDatabase($message)
    {
        ... some code here...
    }
    
}
?>

 

That’s already not fantastic, but if it were only two functions you might argue its not that bad. But what happens when friend 2 wants to store it in Redis and friend 3 wants to store it via FTP, etc, etc, etc.

 

You could always say no! Or you could re engineer your Log class a little to use PHP Dependency Injection.

 

Dependency injection injects a classes dependencies into the class, rather than having the class load and instantiate the objects itself. Another example should clarify things slightly.

 

Continuing with our Log class and the stated desire to have it be able to log to either a database or a file we could create our log class as below, and additionally we would need classes for the database write and the file writer, one of which will be injected into the Log class. Lets take a look at some PHP code:

 

<?php

class Log()
{
    $protected writer = false;
    
    function __construct($writer)
    {   
        $this->write = $writer;
    }
    
    public function log($message)
    {
        if( ($message == "") || ($this->write == false) )
        {
            return;
        }
        
        $message = date("Y-m-d H:i:s")." - ".$message."rn";
        
        $this->writer->log($message);
    }
}



class fileWriter
{
    public function log($message)
    {
        file_put_contents("./fileWriter.log", $message, FILE_APPEND);
    }
}


class databaseWriter
{
    public function log($message)
    {
        $db->insert("log_table", array("message"), array($message) );
    }
}


// do some stuff

$oFileWriter = new fileWriter();

$oDatabaseWriter = new databaseWriter();


// log to file:

$oLog = new Log($oFileWriter);
$oLog->log("This logs to a file");


// log to database

$oLog = new Log($oDatabaseWriter);
$oLog->log("This logs to a database");



Note: in real life I would not do exactly this. For one I’d have an interface with the xxxWriter classes so they knew what to implement. I’d probably also not inject into the log constructor but I might use a setter method. None-the-less this illustrates the point!

 

What we’re doing here is creating multiple Writer classes (fileWriter and databaseWriter). These contain the actual message storage implementation. The Log class contains the filtering and validation and time stamping logic.

 

Our main application creates and instance of the write class it wants to use and the log class and then injects the writer dependency class directly into the Log classes’s constructor or setting function.

 

We’ve now future proofed our Log class! If someone decides they want to store to FTP they need to create an ftpWriter class which implements a log function and they’re good to go!

 

This brief introductory post on PHP dependency injection doesn’t really do the subject justice. My aim is not to give a thesis here but to make it understandable even if you’re a wet behind the ears developer.

Share

Leave a Reply

Your email address will not be published. Required fields are marked *