views:

170

answers:

1

I have a normalized database that stores locations of files on the internet. A file may have multiple locations spread across different sites. I am storing the urls in two parts (Site.UrlStart, FileLocation.UrlEnd). The UrlEnd is the part unique to that file (for the site).

Simplified Db structure:

I am using Zend_Db as my ORM (If it is that), with classes for the tables inheriting from Zend_Db_Table_Abstract.

The issue is that retrieving the location data (e.g. the url) requires the use of multiple tables and as far as I can make out and I would either have to use both table classes (thereby exposing my table structure) or scatter sql all over my application, neither of which sound appealing.

The only solution I can see is to create a façade that acts like Zend_Db_Table_Abstract (Maybe inherits from it?) and hides the fact that the data is actually on two tables.

My questions are as follows:

  • Am I going in the right direction in creating a façade class (Are there other alternatives)?
  • Should the facade class inherit from Zend_Db_Table_Abstract?
+6  A: 

Zend Db Table is not really an ORM beyond very simple use cases. It is meant to be closely related to each table in your system. So, you would have one Zend_Db_Table class for each table.

To manage the bigger picture you would need another type of class.

So, yes, you are on the right lines with regards to using a kind-of façade.

However, I would not make it inherit from Zend_Db_Table_Abstract because it has a very different set of responsibilities.

It might be worth looking into the Data Mapper pattern - which is kind-of like a façade (Martin Fowler, Patterns Of Enterprise Architecture). You'd have one Mapper per 'Type of Domain Entity' (which is not necessarily the same as one per table) and maybe another, extra, mapper for a whole family of types.

A simple example of the Data Mapper patterns is on Zend Framework's intro pages: http://framework.zend.com/manual/en/learning.quickstart.create-model.html

Note how Application_Model_GuestbookMapper uses Application_Model_DbTable_Guestbook - and does not extend it.

However that is quite a simple example and can sometimes leave you with lots more questions than answers.

Another good resource for learning about how to map a db to your model is Scott Ambler's

online article: http://www.agiledata.org/essays/mappingObjects.html

That covers the process of dealing with relationships between data-to-data and object-to-object and data-to-object : http://www.agiledata.org/essays/mappingObjects.html#MappingRelationships

It also touches upon the Data Mapper Pattern and is one of the few places where you see a nice explanation of how to map class hierarchies to db tables.

Also Eric Evans has described the use of 'Repositories', which, are facades that sit between your model and the data layer. This could be a quick starting point if making a fully fledged ORM with Data Mappers seems daunting. You'd generally have one Repository per important Domain Entity (i.e Aggregate Root Entities, 'the stalks of bunches of grapes').

See more about repositories: http://books.google.co.uk/books?id=7dlaMs0SECsC&lpg=PP1&dq=Domain-Driven%20Design&pg=PA147#v=onepage&q&f=false

Basically the Repository has, amongst others, a FindById() type methods which then could encapsulate the use of your three Zend Db Table objects behind its façade. Your model can start using the 'Repo' straight away. Then, one day if you want to add more fancy ORM stuff you just swap it behind the Facade of the Repo and your model does not have to even know about it.

If those three tables represent Entity's that lead independent lives, then it might be best to have three sets of classes that manage each of their life-cycles. If this is the case then you would use 'a Service' (specifically another one of Eric Evans' Patterns) to manage their interactions. A service is a place to put operations that do not seem to fit with any one, exclusive Entity.

see: http://books.google.co.uk/books?id=7dlaMs0SECsC&lpg=PP1&dq=Domain-Driven%20Design&pg=PA106#v=onepage&q=service&f=false

The main point is to psychologically detach yourself from the dominance of Zend Db Table - it is just a minor player, a representation of the db tables and not much more.

JW