My going in "requirements"
-- No dependecy on the ORM from the Domain Objects
-- Support for Lazy Load
-- No extra build step (no pre-run code generation like Propel)
I have a skeletal system that's starting to show promise, but I'm running into a few problems with the first point and I can't look to Hibernate for guidance in this instance.
Hibernate makes relatively few "demands" on the Domain objects:
-- a no args constructor
-- get/setters for all properties (JavaBean)
-- an id field of some kind
and in some sense (not the formal sense) these are all dependcies of the domain layer on the ORM. And I would like to avoid all three if possible. I typically embrace rich constuctors and in some cases have "immutable' objects that I want to persist. Hibernate is able to skirt this issue for the first two as Java's reflection capabilities subvert the private/protected/package/public visibility system. Thus the no-arg and otherwise unneeded setters can be declared private -- or Hibernate can directly access the private attributes via reflection as well (but a non-public no arg constructor is still required)
PHP's reflection system can not bypass the visibility system, so I can't use it to avoid cluttering the domain object's API with un-needed and un-wanted mutators. I could choose to further complicate my mapping language to allow the ORM to "cache" the fields and then invoke a rich constructor; however now the mapping is more brittle to changes in the class API.
Does anyone have ay thoughts on this issue? Anyone know of a way to by-pass visibility protection in PHP?
The isseu of the id field is still outstanding -- there is no reason for the domain object ot have an ID field that only exists for persistence. And I don't want to require one -- ie I don't want surrogate keys pushed into the object model. If a class attribute is a good choice for a natural key, however, that should be allowed.
This issue might be solveable via a good identity map in the ORM layer and I'm also going to have to look into a lot of reference issues to make sure my dirty-field checking system works properly and these two issues are entertwined. The issue could also be "solved" by making the ORM also the "factory" for ALL domain objects, even non-persisted ones, but I'm not sure if I'm willing to take that step.
Currently lazy loading is handled by the ORM creating a proxy on-demand (ie code generation at run time, if the source class file is newer than the auto-generated proxy class). The proxy class extends the real class, so type hinting/etc is preserved. The same mechanism could be used to add the identifier to all cases when needed, if the ORM is used as the domain factory -- create a new class that extends the original and adds an id field with accessor/mutator.
Another alternative I've been pondering is to make the $ormLayer->save($object) return a new object, as desribed above -- class extended with the id field.
Thus the user would do something like
Code: Select all
$domainObject = new Foo("Bar",'Baz");
$domainObject = $ormLayer->save($domainObject);
// $domainObject is now a "FooPersistence" or some other naming conventionAny thoughts here?