Hibernate for PHP?

Ok so first off I know this has been asked before but it does seem to be a few years ago now.

http://www.sitepoint.com/forums/showthread.php?threadid=228431

Does anyone know if there is yet something similar to Hibernate available for PHP? I have been told of Doctorine and Propel but I believe these use the Active Record design pattern
Thanks

As far as I can tell from reading quickly about Hibernate there is little difference in what it offers and what PHP OR/M solutions offer.

Basic mapping between table and class and retreival operations.

Doctrine seems really complex and bloated. The fact it includes validation at the data access layer scares me, considering I’d prefer to do that in my model layer and possibly even in the controller, this is over kill for me.

Like wise the inheritence support makes no sense to me in a stateless environment like PHP applications usually run under.

But I’m curious, what differences do you see in Hibernate and say Doctrine?

Cheers,
Alex

I may be mistaken but it seems to me looking briefly at the docs that Doctrine uses the Active Record design pattern meaning that the Domain relies directly on the Data Access Layer and so creates dependancy. In contrast Hibernate does not have this restriction so have a far looser coupling between Domain and Data Access.

By domain you mean model?

If so that is essentially why I’m being cautious about using Doctrine. I basically want a simple data object to just abstract from the database but not neccessarily the schema, which I believe is what ActiveRecord type solutions accomplish.

Essentially what im looking for is something that i can do this with;


$userMapper = new UserMapper();
$user = $userMapper ->Get(21);
// do stuff with $user

$userMapper ->update($user);
$userMapper->flush();

However it looks like Doctrine does something similar to the following


$user = $userTable->find(21);
// do stuff with $user

$user->save();

In Propel, this is just a convenient shortcut:

$user = UserPeer::retrieveByPk(1);
// do stuff
$user->save();
// is the same as:
UserPeer::doSave($user);

User::save() actually only delegates the work to UserPeer::doSave().

Maybe Doctrine implements this somewhat similarly. The main difference (here, at least, there are others) between Propel and Doctrine is that Propel uses static mappers, which can cause headaches, while you operate with a mapper instance in Doctrine.

regards

That still means that the domain object, User, knows about the UserPeer.

So I suppose the question still stands - does anyone know of an ORM tool like Hibernate/NHibernate which doesn’t require the domain model and DAL to be coupled together like both Propel and Doctrine do?

I suppose leading on from this is that if there is indeed not one, why not?
Thanks

You could write one by subclassing the Zend_db classes, but there’s nothing out of the box which does what you want. It’d be a non-trivial amount of work and it’ll likely end up with application specific dependancies.

Frankly, there are only three ORM layers of anything approaching the level of OO you’re looking for (in no order): Zend_db, Propel, Doctrine. Of the three, Doctrine is most Hibernate-like, but I’m doubtful if PHP5 is upto the OO rigor necessary to actually implment a full-on Hibernate-like ORM. That said, I haven’t been following the latest Doctrine development, so maybe ask the same question over there…

That said, there’s no doubt that ActiveRecord is the center of gravity in PHP-land…

Andrew

It may not be what you are looking for, but it’s for sure an interesting and different approach: http://www.ezpdo.net/blog/?p=840

No, there is currently nothing similar to Hibernate in PHP. Doctrine 2.0 is heading in that direction, so you might want to check it out again in the 3rd quarter of '09 at the earliest.

There are 2 main reasons why something like that does not exist yet:

  1. Its still unclear whether PHP is up to the task in terms of the “heaviness” of such an ORM. People already love to complain about “performance” of almost all larger PHP libraries, “lightweight” seems to be the new cool buzzword.

“WTF, i only get 15 requests/sec” with a hello world-app in symfony/cakephp/whatever?? Screw it!" Then they go on, build their “leightweight” homegrown solutions and at the end the site can be happy if it gets 10 hits a minute. Seriously, come on.

  1. Language “deficits” of PHP. One of the main things needed for “transparent persistence” is a transparent way to get data in and out of the domain objects. Java ORM solutions mostly use reflection, in PHP its only now, with 5.3 ALPHA, possible to get/set private/protected properties through reflection.

There are other problems that make such a “transparent persistence” solution more difficult and potentially more “heavy” than ActiveRecord, like:

  • Change tracking. Hibernate/TopLink/whatever usually keep clones of all objects read from the database so they can compare them with the originals at commit time to determine the changes in the objects.

  • Lazy loading is also much more difficult without an ActiveRecord-style base class. There are many possible solutions here (virutal proxy, ghost, …) but its nevertheless more difficult than just to intercept all calls in an ActiveRecord class ala __get/__set.

The list of reasons goes on and on. Considering these things it should be no surprise that ActiveRecord dominates the PHP scene.

We will see how Doctrine 2 works out, whether it will succeed or not, its nevertheless an interesting challenge. The significant speed bump of PHP 5.3 helps larger php libraries a lot, while “lightweight” libraries might not even notice the difference.

There are two newish PHP projects that both aim to feel a lot like Hibernate for PHP. Outlet ORM and Repose PHP ORM.

Outlet is older and more mature, Repose is newer with slightly different design goals (mainly that it does not rely on having getters and setters to retrieve objects, at the cost of loading more of the object graph at the same time).

Both have similar usage and neither currently require the model classes to extend any base classes or inherit any interfaces.

Example Outlet code.

<?php
$outlet = Outlet::getInstance();
 
$client = new Client;
$client->Name = 'Test Client';
 
$project = new Project;
$project->Name = 'Cool Project';
$project->setClient( $client );
 
$bug = new Bug;
$bug->Title = "Button doesn't work";
 
$project->addBug( $bug );
 
// inserts the project 
// and all of the related entities
// in one transaction
$outlet->save( $project );
?>

Example Repose code.


$session = MyProjectReposeUtil::getSession();
$userBeau = new sample_User('beau');
$userJosh = new sample_User('josh');

$project = new sample_Project('Sample Project', $userBeau);

$bug = new sample_Bug(
    $project,
    'Something is broken',
    'Click example.com to test!',
    $userJosh, // Reporter
    $userBeau // Owner
);

$session->save($bug);

  1. Language “deficits” of PHP. One of the main things needed for “transparent persistence” is a transparent way to get data in and out of the domain objects. Java ORM solutions mostly use reflection, in PHP its only now, with 5.3 ALPHA, possible to get/set private/protected properties through reflection.

Repose has a workaround for dealing with protected properties and has planned support for private properties with PHP >= 5.3. The hope is that people using PHP < 5.3 will continue to be able to use protected properties and anyone who has access to PHP >= 5.3 will be able to use private properties if they need to.

I’ll have to take a look at Doctrine 2.

I wonder, though, how PHPers became religious about visibility restrictions. In PHP 4, everything was public, and I never saw a problem in keeping the discipline of not using them except through accessors. Transparent persistence is a far more important issue with much wider implications. As is testing.

That sounds more like a coder preference than anything specifically to do with php.

As dagfinn mentioned, you don’t have to set your properties as private. You could also set up the ORM to use getters/setters.

There are a couple of ways to do this, storing a clone is only one of them. Any decent UoW implementation should be able to keep track of dirty/clean objects.

Is lazy loading really that difficult? I’ve already implemented wrappers that lazy load and lazy batch load objects/collections… the classes weren’t that complex, they just stored a callback to a DataMapper and executed the callback on first access. __get/__set/__call delegates to the returned value. If you really wanted to get fancy, you could implement some runtime subclassing so the wrapper would satisfy type hints.

I would like to hear more of these reasons. So far I’m not sold.

If you like that syntax, you will probably really like phpDataMapper. The syntax is almost exactly the same, with the same ideas behind it, like $mapper->save($user) instead of $user->save().

Sure, its no issue if you’re the only one developing the app and if you adhere to your conventions. As soon as you’re faced with a very big software, developed by dozens of different developers you’ll beg for the ability to define visibility rules to prevent people from (accidentily or not) messing with your internal state.

I will not explain the concept of data hiding here. An ID field, for example, should usually not be publicy reassignable. If the ORM tool forces you to reveal data you dont want to reveal just to get it persisted, thats already quite a restriction. Good API design is a different and very difficult topic.

Yes, sure, its easy to say that. Did you really ever implement a full-blown unit of work that keeps track of clean/dirty/removed/… objects and collections, and all the features going along with it and at the end properly ordering all operations so as to not violate referential integrity among other things … ?
I do not call that simple at all. You should check out the Hibernate Core or TopLink (now EcliseLink) sources and investigate…

Not to speak of the overhead of maintaining the clones.

(If there is such a “decent UoW” implementation in PHP out there please point me to it!)

I know the ways to do it, but it’s certainly more difficult than just intercepting some calls in a base class and then loading the data if its not there. Virtual proxies (i assume thats what you used, too from your description) are one way to do it but ideally they should not really be visible to the user.

Well, another big point is implementing a parser and SQL generator for the OQL that generates DBMS-dialect specific SQL but I guess thats also just peanuts from your point of view :rofl:

Seriously, if you never really implemented such a full-blown ORM and didnt look at the sources of projects like Hibernate or EcliseLink yet (you should do so! quite interesting!) then you can hardly imagine how much work this requires. Thats why I find it so funny why people are wondering “Huh? Why theres no hibernate for php?”. If its so easy, go make one, I would LOVE to use it!

[irony](Of course it must be super-performant and lightweight! Faster than mysql_query preferrably![/irony]

What do you mean by “not really be visible to the user”? The user wouldn’t know the difference unless you’re checking the type of the class. Can you explain why this method would not work? What makes it difficult?

That would be nice, but is that a critical component of an ORM? I couldn’t care less about duplicating all of the features of Hibernate… All I want is an ORM that doesn’t use ActiveRecord and doesn’t require extending a base class.

And why wouldn’t they be checking the type? For one thing, PHP does a lot of magic that can be enabled in user-made objects by implementing a specific interface, say ArrayAccess. Are you going to go ahead and implement all of those magic interfaces in the proxy class? Even if you do, it still wouldn’t be flawless and the only reasonable approach typewise would be runtime generation of a subclass of the model object you’re handling. What you get is a situation not altogether different from the original where record objects actually extend a Record class that handles this, but the dependency would be implicit and such an implementation would come with quite a few performance and other related issues.

What you haven’t told us is why sharing a base class is such a big problem for you. Our company has went through a few projects with first Zend_Db and now Doctrine and havent seen any problem with the approach.

That would be nice, but is that a critical component of an ORM? I couldn’t care less about duplicating all of the features of Hibernate…

What use is your data if you can’t query it in a useful way? If not an OQL or a similar layer such as LINQ on top, how would you like to access your data? Raw SQL? Wouldn’t that negate much of the advantage you’re trying to achieve with an ORM?

That’s where I was going next (runtime subclassing). I’m just curious what problems this method of lazy loading has, aside from type hinting (which I was already aware of).

If I’ve implied that I think all domain objects extending a base class is a bad thing overall, I apologize. I was merely expressing my personal preference. I’m really not criticizing anyone’s approach… I am just curious as to what exactly makes ORMs difficult to build.

Domain-specific methods, for one, and yeah, I don’t have a problem with raw SQL if complicated queries are needed. At least if you’re trying to keep things simple, which I am.