Testing out Doctrine

For a good while I was thinking about a bigger cut in the core which I want to discuss, as I wondered if we are perhaps doing too much unneeded effort with the 2.0 core. During the first steps to our new architecture (see this earlier post) doubts came into my mind about what we *are doing* and what we *should do*.


Huh! What is this about?

This relates to adodb, the DBUtil/ZDB*classes as well as PNObject/ZObject which build our db and orm (object-relational mapping) layers. The latter one is a modern layer encapsulating the db layer. Perhaps you know orm from Hibernate in Java already. Currently our core has some nice orm features, like session storage, validation, serialization and so on. The matter is if we really want to develop and maintain these layers for our own, which takes a quite much degree of the overall core development efforts at the moment.

Pragmatically speaken we are doing much work which is neither required nor our "job". There is a reason why there exist specialized projects for both the db and the orm layers - they "want" to be outsourced icon_smile Actually in most of the development time we should be able to concentrate on *what makes up Zikula* - and this is definitely not an orm layer. Nobody of us is a real database freak, otherwise we would also develop our own adodb. We use databases, not more. So how it works under the surface, is not specific to our project in any kind. We also did not develop our own Smarty and Prototype icon_smile The idea is very simple: the more of the maintenance of our system we can outsource to others the quicker development is and the less bugs we must deal with.

After having thought about that I think it would be smarter to use an external project for that purpose. In detail there are at least two interesting orm frameworks available for PHP: Propel or Doctrine. Both are based on PDO (PHP Data Objects) database abstraction which is part of PHP since 5.1. It seems like Doctrine is offering more comprehensive means and also did have a more active development recently. Symfony is supporting both by treating them as orm plugins within a shared meta layer.

How about Doctrine? Sounds weird. Does it cover everything we need?

Doctrine is offering some more enhanced features (which are very useful for a web tool kit like Zikula). It contains some really powerful stuff, including for instance many2many relationships, migration functionality, data validation, inheritance, as well as self referencing ones. Most other ORM frameworks for PHP are far behind that. Very interesting are behaviors allowing registering listener components to database activities (similar to triggers), perfect for things like the standard fields created by ObjectUtil (e.g. cr_uid and lu_date).

What are the benefits? What are the costs?

Pro arguments:

  • using a standard
  • pragmatic way to have less maintenance work (e.g. less fixes for specific dbms)
  • chance for a new architectural approach based/focused on clear layers (decrease coupling within the object library)
  • solves overlappings between ZObject and pnForm (for instance when it comes to validation)
  • well-known and common-used libraries might attract further developers (PDO, Doctrine itself)
  • we can include the Doctrine framework into our own marketing
  • taking use of functionality which is built-in in PHP5 and will be actively supported in future (PDO)
  • less size of our package, as adodb will be removed in 3.0
  • the same legacy layer effort as we also have with ZDB* classes (the difference is that we don't have to invent those classes)

Con arguments:

  • to save performance we will probably have to write some own queries at some places or implement them into the layer

You have been pushing DBUtil for a long time now. Are you making fun of us?

Initially DBUtil was meant to have another abstraction layer to be quite independent of adodb and use different db layers under it. So where is the reason to change this intention? The facts are that these are different layers: The database layer is currently covered by adodb, the potential candidate is PDO. The orm layer is currently handled by DBUtil and ZObject, the potential candidate is Doctrine.

So as a nice side effect our package becomes smaller after adodb got dropped if we switch to PDO implicitely. As said PDO is included in PHP, so with PHP5 there is no need to carry an own db abstraction lib around.

When DBUtil has been written by Robert, no solutions like Propel and Doctrine existed yet. In the meanwhile a lot has changed in the php world with which we have to cope with (see the earlier post to read more about the changes for php5). Logically it is simply the next step to outsource not only the db layer, but also the orm layer.

So this whole thing is not against DBUtil or something else in the object library, it simply aims on the technological progress. Historically DBUtil was simply necessary to push certain developments and make things like ZObject possible. The matter is that we could save a huge amount of work and use the free time to concentrate on other things, like clean enhancements for ZObject which is the real highlight and should be boosted after the architectural clean ups have been finished. A ZObject will then extend a Doctrine_Object.

Stop advertising! Will I have to rewrite my module?

No, not really. The funny aspect is that our refactored version of DBUtil (the ZDB* classes) would be covered completely by the Doctrine internals. Again the only difference is that the new stuff must not be invented by ourselves. If we use Doctrine, we don't need ZDB* anymore. So we decided to evaluate that now, before we put the next big effort into 2.0.

Also other tasks are independent of that decision. We need a legacy layer for bridging existing code anyway. We have to change some system modules to use the object classes anyway. No panic, DBUtil or adodb will not be gone suddenly, but live beside all these object-oriented improvements icon_wink

So all current extensions will keep working without bigger changes. Nevertheless we will care on improving documentation and creating a separate "how to migrate my module in 10 minutes" tutorial.

How to cope with the migration? This sounds very complicated :S

We must make sure not to compromise the Zikula specific advantages or lose important features we have at the moment. The problem behind the migration effort is that DBUtil is not strictly separated from ObjectUtil. As outlined earlier (see the earlier post), all the additional DBUtil services (e.g attributes, metadata, categories) will become ZObjectDecorator instances, extending a ZObject by additional functionality during runtime. But this is a challenge which is independent of whether we continue the own layers using ZDB* or introduce another thingy. So if we keep all this nice functionality, we have nothing to lose and everything to gain.

Probably the integration efforts are lower than maintaining the own layer under the line. I think about the following proceeding for concrete implementation in Zikula:

  1. include Doctrine into 2.0
  2. refactor ObjectUtil services to ZObjectDecorator instances
  3. rewrite ZObject to a wrapper of a Doctrine_Object (like Renderer extends Smarty)
  4. declare DBUtil and adodb as obsolete in 2.0
  5. implement some classes taking care for legacy bridging
  6. remove DBUtil and adodb in 3.0

And now? How to go on?

First I talked with several core devs to ensure that I have their general support for this sub project. The next primary goal is to get a final decision soon - before doing more work at 2.0. Thus Drak created a new experimental branch based on the 2.0 core line. In this branch we are going to play around and do some testing with Doctrine to see how it behaves in practice in order to become able to estimate migration efforts and other relevant metrics more concretely.

If you want you might take a look into the Doctrine documentation to get a feeling for that tool.

If you have any questions about this topic, know Doctrine and/or want to contribute to these developments, please feel free to comment or contact the Steering Committee at sc@zikula.org icon_smile

Thank you for reading!


Share This | Print

Trackbacks

(The URL to TrackBack this entry is: http://blog.zikula.org/index.php?module=TrackBack&id=26,1-48). If your blog does not support Trackbacks you can manually add your trackback by using this form.

Comments

Comment by:
Mateo's Avatar
Mateo
22 Mar 2009 - 03:34AM
Very interesting stuff
Very nice to have a previous study about the path to follow, and i'm concerned about the DBUtil and if it got deprecated, some PHP coders that doesn't manage the O.O. stuff pretty well will be blocked i guess.

Is there a remote possibility to maintain the O.O. and structural programming stuff supported for third party modules?

Have to think about how to engage the third partu development because even with our current scheme, some third party devs seems to be blocked already...

Anyways, will be very nice to have Doctrine in the core. Anything i can do to contribute, count with me icon_wink
 
Comment by:
mumuri's Avatar
mumuri
22 Mar 2009 - 02:51PM
outsourced db layer ...
I totally agree with this.

1- Concerning Hibernate/EJB etc ..., there is still a problem with them. As they add a "layer" on the code, we can be limited in some case (in the company where i have done an internship, they had to give up the project because of that, now they use JDBC with a code generation framework).

So my question is simple, is there some way in some case to do our query with a normal sql query in Doctrine, in order to avoid the problem mention above.

EDIT : i think it's possible , i ve seen this piece of code
$q = Doctrine_Query::create()
->from('User u')
->where('u.id NOT IN (SELECT u.id FROM User u2 INNER JOIN u2.Groups g WHERE
g.name = ?)', 'Group 2');


2- Moreover , are those projects active and use by big company ?

3- Will you use yaml or php based classes ? yml seems to be pretty complex

4- And finally, why don't you use Zend DB ? (they used in many companies). Note that doctrine seems to put all "layers" in one object without separation (facade/dao/entity), why do you wan't to use this one ?
 
Comment by:
mumuri's Avatar
mumuri
22 Mar 2009 - 03:15PM
thought about object aspect in zikula
5- I don't like the way doctrince handle "entity" (user , group ...) stuff, indeed, they seems to put all layer in one object
, in my opinion, an entity should only have getter and setters

classe user extends Entity {

function setName(){
...
}

function getName(){
...
}

...
}


and then we could have an equivalent to pntables.php with an object aspect

for instance

classe userTable extends Doctrine_Record{

function setTableDefinition(){
...
}


...

}


6- like in 5, we could separate the data mapping layer ( DAO in J2EE) and the entity layer, for instance

classe userDataMapper extends DataMapper{

function load($id){

}

function save( (User)$user){
...
}


function search ($parameters){
...
}
}


7- usually you don't call only one function from the DataMapper, so there is perhaps a need to introduce a Facade layer


classe userFacade extends Facade{
function loadFull($id){
$userDataMapper = FactoryDataMapper::load("user");
$user = $userDataMapper->load($id);

$groupDataMapper = FactoryDataMapper::load("group");
$group = $groupDataMapper->load($user->getGroup()->getId());

$user->setGroup($group );

return $user;

}

}

8- finally ,a zikula module project could have this structure ...

modules/user/facade
modules/user/facade/userFacade.php
modules/user/facade/otherFacade.php
modules/user/datamapper
modules/user/datamapper/userDataMapper.php
modules/user/datamapper/otherDataMapper.php
modules/user/entity
modules/user/entity/user.php
modules/user/entity/otherEntity.php
modules/user/db
modules/user/db/userTable.php
modules/user/db/otherTable.php
... pnTemplate, Javascript, Images classical folders ..
modules/user/pnuser.php // MVC - smarty part
modules/user/pnadmin.php // MVC - smarty part


9- i agree with mateo , DBUtils can't be deleted , BUT perhaps it's possible to replace the content of all the method in it with
equivalent in "Doctrine" language. Thus, DBUtils, will become a facade for doctrine, which will allow people to have a retro compatibilty
for old modules and allow developer to continue coding modules without real object aspect

10- about multisites & doctrine, is there a way to handle this ?


And sorry, i really don't have time to contribute the developpement, but i will follow the evolution of this stuff, hope my ideas will
interest you
 
Comment by:
guite's Avatar
guite
05 Apr 2009 - 11:29AM
A good weekend
Yesterday and today Frank (Landseer) and me dived into the Doctrine internals and we changed most important parts of DBUtil to use it instead of adodb.
We can already tell that all your suggestions can be considered (nothing is impossible), but we will have to do it well-thought and therefore step by step though.
After the implementation has grown to a more complete state, another article will follow.
 

Add a new Comment









 
Close

You don't have permission to e-mail this story - please login