PHP Design Patterns – Validating Repository Pattern Implementation

design-patternsPHPrepository

I've been reading up about the repository pattern, with a view to implementing it in my own application. Almost all examples I've found on the internet use some kind of existing framework rather than showing how to implement it 'from scratch'. Here's my first thoughts of how I might implement it – I was wondering if anyone could advise me on whether this is correct?

I have two tables, named CONTAINERS and BITS. Each CONTAINER can contain any number of BITs. I represent them as two classes:

class Container{
    private $bits;
    private $id;
    //...and a property for each column in the table...

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

    public function addBit($bit){
        $this->bits[] = $bit;
    }

    //...getters and setters...
}

class Bit{
    //some properties, methods etc...
}

Each class will have a property for each column in its respective table. I then have a couple of 'repositories' which handle things to do with saving/retrieving these objects from the database:

//repository to control saving/retrieving Containers from the database
class ContainerRepository{

    //inject the bit repository for use later
    public function __construct($bitRepo){
        $this->bitRepo = $bitRepo;
    }

    public function getById($id){
        //talk directly to Oracle here to all column data into the object 

        //get all the bits in the container
        $bits = $this->bitRepo->getByContainerId($id);
        foreach($bits as $bit){
            $container->addBit($bit);
        }

        //return an instance of Container
    }

    public function persist($container){
      //talk directly to Oracle here to save it to the database
        //if its ID is NULL, create a new container in database, otherwise update the existing one

        //use BitRepository to save each of the Bits inside the Container
        $bitRepo = $this->bitRepo;
        foreach($container->bits as $bit){
            $bitRepo->persist($bit);
        }
    }
}

//repository to control saving/retrieving Bits from the database
class BitRepository{
    public function getById($id){}
    public function getByContainerId($containerId){}
    public function persist($bit){}
}

Therefore, the code I would use to get an instance of Container from the database would be:

$bitRepo = new BitRepository();
$containerRepo = new ContainerRepository($bitRepo);
$container = $containerRepo->getById($id);

Or to create a new one and save to the database:

$bitRepo = new BitRepository();
$containerRepo = new ContainerRepository($bitRepo);

$container = new Container();
$container->setSomeProperty(1);
$bit = new Bit();
$container->addBit($bit);
$containerRepo->persist($container);

Can someone advise me as to whether I have implemented this pattern correctly? Thanks!

Best Answer

The implementation looks correct for me.

The approach may not scale well, because:

  • You recreate an object every time in getById,

  • You loop through all the objects in persist, while maybe only one changed,

But doing premature optimization would be worse: if performance corresponds to your expectations right now, don't change anything.

Later, if performance becomes an issue, consider:

  • Implementing caching strategy (given that it will probably be outside the repository, as an additional layer between the repository and the code which uses the repository),

  • Using observer pattern to track the changes in the objects: this way, when persisting changes, you don't need to do extra work, and can update only the data which actually changed.

Related Topic