SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 29
  1. #1
    SitePoint Member
    Join Date
    Oct 2007
    Location
    East Sussex
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    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/show...hreadid=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

  2. #2
    SitePoint Evangelist
    Join Date
    Aug 2005
    Location
    Winnipeg
    Posts
    498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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
    The only constant in software is change itself

  3. #3
    SitePoint Member
    Join Date
    Oct 2007
    Location
    East Sussex
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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.

  4. #4
    SitePoint Evangelist
    Join Date
    Aug 2005
    Location
    Winnipeg
    Posts
    498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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.
    The only constant in software is change itself

  5. #5
    SitePoint Member
    Join Date
    Oct 2007
    Location
    East Sussex
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Essentially what im looking for is something that i can do this with;

    PHP Code:
    $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
    PHP Code:
    $user $userTable->find(21);
    // do stuff with $user

    $user->save(); 

  6. #6
    SitePoint Guru dbevfat's Avatar
    Join Date
    Dec 2004
    Location
    ljubljana, slovenia
    Posts
    684
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Gee Bee View Post
    Essentially what im looking for is something that i can do this with;

    PHP Code:
    $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
    PHP Code:
    $user $userTable->find(21);
    // do stuff with $user

    $user->save(); 
    In Propel, this is just a convenient shortcut:
    PHP Code:
    $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

  7. #7
    SitePoint Evangelist
    Join Date
    Mar 2006
    Location
    Sweden
    Posts
    451
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dbevfat View Post
    In Propel, this is just a convenient shortcut:
    PHP Code:
    $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().
    That still means that the domain object, User, knows about the UserPeer.

  8. #8
    SitePoint Member
    Join Date
    Oct 2007
    Location
    East Sussex
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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

  9. #9
    SitePoint Member
    Join Date
    Oct 2005
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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

  10. #10
    SitePoint Enthusiast
    Join Date
    Jun 2007
    Posts
    27
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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

  11. #11
    SitePoint Member romanb's Avatar
    Join Date
    May 2006
    Location
    Berlin
    Posts
    22
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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.

    2) 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.

  12. #12
    SitePoint Member simensen's Avatar
    Join Date
    Jan 2009
    Posts
    1
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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 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.

    PHP 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); 
    2) 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.
    Last edited by simensen; Jan 14, 2009 at 14:25. Reason: New info.

  13. #13
    SitePoint Guru dagfinn's Avatar
    Join Date
    Jan 2004
    Location
    Oslo, Norway
    Posts
    894
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by romanb View Post
    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.
    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.
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  14. #14
    Spirit Coder allspiritseve's Avatar
    Join Date
    Dec 2002
    Location
    Ann Arbor, MI (USA)
    Posts
    648
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by romanb View Post
    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.
    That sounds more like a coder preference than anything specifically to do with php.

    Quote Originally Posted by romanb View Post
    2) 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.
    As dagfinn mentioned, you don't have to set your properties as private. You could also set up the ORM to use getters/setters.

    Quote Originally Posted by romanb View Post
    - 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.
    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.

    Quote Originally Posted by romanb View Post
    - 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.
    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.

    Quote Originally Posted by romanb View Post
    The list of reasons goes on and on. Considering these things it should be no surprise that ActiveRecord dominates the PHP scene.
    I would like to hear more of these reasons. So far I'm not sold.

  15. #15
    PHP/Rails Developer Czaries's Avatar
    Join Date
    May 2004
    Location
    Central USA
    Posts
    806
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Gee Bee View Post
    Essentially what im looking for is something that i can do this with;

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

    $userMapper ->update($user);
    $userMapper->flush(); 
    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().

  16. #16
    SitePoint Member romanb's Avatar
    Join Date
    May 2006
    Location
    Berlin
    Posts
    22
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dagfinn View Post
    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.
    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.

  17. #17
    SitePoint Member romanb's Avatar
    Join Date
    May 2006
    Location
    Berlin
    Posts
    22
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by allspiritseve View Post
    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.
    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.

    Quote Originally Posted by allspiritseve View Post
    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.
    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!)

    Quote Originally Posted by allspiritseve View Post
    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 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.

    Quote Originally Posted by allspiritseve View Post
    I would like to hear more of these reasons. So far I'm not sold.
    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

    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]

  18. #18
    Spirit Coder allspiritseve's Avatar
    Join Date
    Dec 2002
    Location
    Ann Arbor, MI (USA)
    Posts
    648
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by romanb View Post
    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.
    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?

    Quote Originally Posted by romanb View Post
    Well, another big point is implementing a parser and SQL generator for the OQL that generates DBMS-dialect specific SQL
    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.

  19. #19
    SitePoint Guru
    Join Date
    May 2005
    Location
    Finland
    Posts
    608
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by allspiritseve
    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?
    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?

  20. #20
    Spirit Coder allspiritseve's Avatar
    Join Date
    Dec 2002
    Location
    Ann Arbor, MI (USA)
    Posts
    648
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ezku View Post
    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.
    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).

    Quote Originally Posted by Ezku View Post
    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.
    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.

    Quote Originally Posted by Ezku View Post
    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?
    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.

  21. #21
    SitePoint Enthusiast
    Join Date
    Feb 2004
    Location
    Montreal
    Posts
    77
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I have come up with something that can, in no way, be compared to Doctrine or Propel. It does, however seem to work pretty well for me. It was built with ease of use in mind. I feel that things in PHP should take a minimum of lines or the interface may be cumbersome. I will show a couple of its paradigms and you may possibly find it interesting.

    PHP Code:
    // Initialize using the built-in DBA layer (I needed to run this in a non-PDO environment)
    // AFAIK, you could just as easily use FAPersistence::connect(new PDO('...'));
    $orm FAPersistence::init('mysql://user:pass@host/database');

    // Find a user the suggested way
    $user $orm->User(4);

    // Otherwise, the long way
    $user = new User(array('id' => 4));
    $user->find();

    // Note that if both ways were used on the same page request, they would nevertheless contain references to a common record object.

    // Find all users
    $users $orm->findAll('User');

    // Find users who joined in the last day
    $users $orm->findAll('User')->where('User.joined > CURDATE()-1'); // I'm not sure about the SQL, but that's not the point

    // Find all users ordered by their full name
    $users $orm->findAll('User')->orderBy('User.fullname');

    // Method chaining for simple updates
    $orm->User(4)->set('fullname''Real Name')->save(); 
    The entities returned through these queries all implement __get and __set magic methods (not shown above).

    Thoughts?

  22. #22
    SitePoint Member
    Join Date
    Mar 2009
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I've been working in a project like hibernate for PHP. Been 3 years since i began and right now im having some problems with the language.
    Since it cant "runtime extend" a class, its kinda hard to implement lazy fetch proxying if you are using type hinting. Unless your server suports runkit allowing best AoP in PHP. There are other issues as well but it runs fine and after it became stable (documented in my home language Brazillian Portuguese, tho) never needed to declare SQL statements anymore, but i realize that it cant do complex reports yet. If you are interested i can provide the code and later on translated docs.

  23. #23
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by seelaz View Post
    Since it cant "runtime extend" a class, its kinda hard to implement lazy fetch proxying if you are using type hinting.
    Interfaces?

  24. #24
    SitePoint Member
    Join Date
    Mar 2009
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    even using interfaces... i assume you'll hint your parameter with the class it expects. if its a interface you'll need a proxy implementing it or make your classes implement an fw interface. I do the trick using annotations (phpDocComment parsed with regex and extending the reflection classes to suport them) and i tried hard to not force inheritance or interface implementations... seems that i have to face it cant be done like i want right now. Dont want to ask for hinting removal also....

  25. #25
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by seelaz View Post
    even using interfaces... i assume you'll hint your parameter with the class it expects.
    The point of interfaces is pretty much that you typehint to the interface, not the concrete class. You would be forcing the user to write code this way, yes, but that wouldn't be too bad.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •