Alex Rivera | Logout

PHP DataMapper with multiple persistence layers

Asked 2012-10-25T08:07:09.870
8

I am writing a system in PHP that has to write to three persistence layers:

  • One web service
  • Two databases (one mysql one mssql)

The reason for this is legacy systems and cannot be changed.

I am wanting to use the DataMapper pattern and I am trying to establish the best way to achieve what I want. I have an interface like follows:

<?php
    $service = $factory->getService()->create($entity);
?>

Below is some contrived and cut down code for brevity:

<?php
class Post extends AbstractService
{
    protected $_mapper;

    public function create(Entity $post)
    {
        return $this->_mapper->create($post);
    }
}

class AbstractMapper
{
    protected $_persistence;

    public function create(Entity $entity)
    {
        $data = $this->_prepareForPersistence($entity);
        return $this->_persistence->create($data);
    }   
}
?>

My question is that because there are three persistence layers, there will also therefore likely be a need for three mappers for each. I'd like a clean design pattern inspired interface to make this work.

I see it as having three options:

  1. Inject three mappers into the Service and call create on each
  2. $_mapper is an array/collection and it iterates through them calling create on each
  3. $_mapper is actually a container object that acts as a further proxy and calls create on each

Something strikes me as wrong with each of these solutions and would appreciate any feedback/recognised design patterns that might fit this.

Edit
Report

1 Answer

2

I have had to solve a similar problem but very many years ago in the days of PEAR DB. In that particular case, there was a need to replicate the data across multiple databases.

We did not have the problem of the different databases having different mappings though so it was a fair bit simpler.

What we did was to facade the DB class and override the getResult function (or whatever it was called). This function then analysed the SQL and if it was a read - it would send it to just one backed and if it was a write, it would send it to all.

This actually worked really well for a very heavily utilised site.

From that background, I would suggest entirely facading all of the persistence operations. Once you have done that, the implementation details are less relevant and can be changed at any time.

From this perspective, any of your implementation ideas seem like a reasonable approach. There are various things you will want to think about though.

  • What if one of the backends throw an error?
  • What is the performance impact of writing to three database servers?
  • Can the writes be done asynchronously (if so, ask the first question again)

There is potentially another way to solve this problem as well. That is to use stored procedures. If you have a primary database server, you could write a trigger which, on commit (or thereabouts) connects to the other database and sychronises the data.

If the data update does not need to be immediate, you could get the primary database to log changes and have another script that regularly "fed" this data into the other system. Again, the issue of errors will need to be considered.

Hope this helps.

answered 2013-02-24T19:28:17.453

Your Answer