The lost age of innocence.

Posted 7 years ago.

Pomm has been under development for a while. It was aimed at being simple, fast, lightweight and efficient. I must say I am pretty happy of what it has become over time and I was very exited when I did implement the filter feature because it made Pomm able to simulate relations between objects. This was also the starting point of a the research for a way to keep consistency between fetched objects from the database.

A dumb implementation meant 1 instance per fetch, if an object is fetched twice from the database it would have two instances of the same class and the same values. As soon as you create an OO relation using a JOIN it becomes a problem.

Fortunately Pomm is far from being the first database Object Mapper and this problem has a solution in the name of the Identity Mapper design pattern. This pattern uses an index of fetched objects to ovoid fetching them twice from the database. From my point of view, this makes sense in the Java world where there are application servers that keep running for days and months. In PHP the environment is different. The whole world is instanciated once, the response is sent and then all instances die. This lowers the benefits of the Identity Mapper while making it downsides stronger.

Keeping an index of all fetched object prevent PHP's garbage collector to work efficiently as we keep at least an instance in the index. Even if I want to be smart and try to check if this instance is modified or not, if I just fetch an instance from the database, modify it and unset it, there is no way I'll be able to fetch this object again from the database, the identity mapper will keep returning me the same broken instance.

Because it can be bug and feature, I wanted to let the developers be able to manage the IdentityMapper in Pomm. The first question was "Where to store it ?". In the map classes ? As a separate service ? The place I felt the more comfortable with this was the Connection class. You can set a default IdentityMapper class in the database options, but you can also provide an instance in the createConnection() method of the Database class.

There are 3 different possible classes to choose from: IdentityMapperNone, IdentityMapperStrict and IdentityMapperSmart. The None one is when an identity mapper has been declared for all connections and you explicitly wants none. The strict is very simple: instances are stored and retrieved from the mapper. If you delete an instance from the database, do not forget to unset it from the mapper as well or it will keep providing you with the deleted instance. The smart tries to be a bit more clever. If the instance it got is in the deleted state, it removes it. If the instance it helds has not been modified, values from a fetched objects are merged to the existing instance.

Of course this does not recover from all the problems the IM can provide but this may be a good compromise in PHP where the goal of this design pattern is not so to limit the query number -- especially with Pomm where developers have a great control over the queries -- but to ensure to keep the existing instances consistent. I think Pomm has made its way to a stable release ... Stay tuned !