Using Interfaces for Repositories in PHP

Saturday, August 08 2009

I’m working on a restructuring/re-design of the web site VGMusic. This is my first attempt at applying such delightful techniques such as the Repository Pattern and Dependency Injection in PHP, and that language does not make this easy. Support for object-oriented techniques is not the best, and the biggest obstacle is the fact that PHP is weakly typed. This makes it really difficult to do things like program against an interface. If I wrote the line:

<?php
$fooRepository = new FooRepository();
?>

Then I’m actually instantiating an instance of the concrete implementation FooRepository(). What I would like to do, however, Is use the interface IFooRepository instead. What I decided to do is to take a page out of the MVC Pattern and use controllers. A controller can have a private instance of a repository.

<?php
class FooController
{
    private $_fooRepository;
    
    function __construct(IFooRepository $fooRepository)
    {
        $this->_fooRepository = $fooRepository;
    }
 
    public function GetFoo($id)
    {
        return $this->_fooRepository->GetFoo($id);
    }
}
?>

Now I can pass in any class, including fakes, that implements IFooRepository (thankfully Type Hinting allows me to restrict what type of variable is passed into the constructor). It’s still not technically programming against an interface, but it’s the solution I’ve chosen to go with. In addition to doing this, I would also like to have a default constructor for the controller that just uses the default implementation for the repository. Since PHP does not allow for overloaded constructors, I will fake a parameterless constructor by giving $fooRepository a default value of null:
 
<?php
class FooController
{
    private $_fooRepository;
    
    function __construct(IFooRepository $fooRepository = null)
    {
        if ($fooRepository = null)
        {
            $fooRepository = new FooRepository();
        }
        $this->_fooRepository = $fooRepository;
    }
}
?>

If I create a new instance of a FooController without passing parameters, the default repository will be used. I also wanted to use controllers to begin with, lest my PHP code start looking like classic ASP where both the business logic and UI-related logic end up in a gigantic if-then-else block in a single PHP file. When it comes to using these techniques that I’ve learned a great deal about over the past few months, PHP leaves a lot to be desired. Hopefully I can make it through this project without running into many more obstacles.