Re: New PDO-based DBAL/ORM for PEAR2
| From: | Michael J. I. Jackson | Date: | Tue, 20 Nov 2007 17:51:09 +0000 |
| Subject: | Re: New PDO-based DBAL/ORM for PEAR2 | ||
| References: | 1 2 | Groups: | php.pear.dev |
| Request: | Send a blank email to pear-dev+get-48515@lists.php.net to get a copy of this message | ||
On Nov 20, 2007, at 6:36 AM, Bertrand Mansion wrote:
It looks good. I personally would remove the datatype and manager stuff, as well as most of the things related to SQL abstraction since this is a myth and adds bloat in the package (sequences and dates to start with).I did cut back on both the Datatype and Manager modules considerably, and just kept the stuff from MDB2 that I felt was pretty solid. There were a few functions that were labeled experimental or that did not have very well defined argument lists (i.e. alterTable(), etc.) that I chose to exclude for the time being. However, the beautiful thing about the module classes is that they're never loaded if you don't need them. So don't use them and performance stays high. Besides, the only time somebody would actually ever use the Datatype or Manager classes would be to create/drop databases, tables, sequences, etc...stuff that is rarely done, and probably done at night when everybody is asleep. ; )
I'd call Drivers -> ConnectionsAgreed.
and remove the singleton method.Why?
I wouldn't make a difference between one-to-one and one-to-many relations.I did this so that I could create type-safe collections of domain objects instead of just arrays. I will post some domain layer usage notes to the wiki soon.
I don't think subclassing PDO_Statement is needed. I am not sure a Query class is needed, everyone knows SQL.Agreed. Neither are needed. They're mainly for convenience. The Query class isn't even loaded unless you want to use it.
The Domain layer is a good idea but is hard to implement correctly in PHP. I'd add triggers after insert/delete/update/select (didn't find them, maybe it's in already?).There are triggers on query() and exec() already (these will be fired on every select, insert, update, delete). I'm still sorting out the details of the domain layer (as you said, it's difficult to implement correctly) so that is a definite possibility.
I also have a PDO/ORM class but it doesn't deal with abstraction, so switching from MySQL to Oracle means you probably have to rewrite a few queries (the ones with outer joins for example, but limits are dealt with correctly). It looks a lot like yours but seems better integrated with PDO and PHP (uses little known PDO features and a lot from SPL).If you know some PDO features that I'm not currently using, please let me know. I purposefully did not extend PDO because this makes it difficult to close/reopen connections. Other than that, I've tried to leave the API flexible enough for future improvements to PDO and I've also tried to let the underlying PDO functionality shine through.
It uses delegates on overloaded methods and on ArrayAccess methods. It caches the database mapping on request. It can autoload object classes too. It works like this: Phreez::connect($pdo); // or Phreez::getConnection() if connection exists, accepts a connection id. $author = Phreez::fetchOne('author', array('where'=>'name = ?'), array('Jack Vance')); $book = Phreez::factory('book'); $book['title'] = 'The killing Machine'; $book->setAuthor($author); $book->freeze(); foreach ($author->getBooks() as $book) {The domain layer also has this functionality. A little bit different syntax, but the same things are possible: $a_mapper = Mapper_Author::getInstance(); $author = $a_mapper->find(3); // find author object with primary key 3 echo $author->first_name; // overload __get and __set methods provide pseudo access to fields foreach ($person->books as $book) {echo $book['title'];} Thanks to a Translation delegate, you can also do: foreach ($author->getBooks(array('order by'=>'title DESC')) as $book) {echo $book['fr']['title']; echo $book['en']['title'];}
// do something with each book...} I'm also working on making these domain classes inheritable. Now that's the tricky part! ; )
I first tried with decorators instead of delegates, but PHP has problems dealing with memory for the decorator pattern. And delegates are apparently faster in my benchmarks. The main thing I miss compared to your package is the Domain stuff which means loading twice the same object from the database is unfortunately possible if user doesn't pay attention. I find it difficult to find a good way to deal with this issue so I will have a close look at your implementation. Using pure SQL I can also do things like: $authors = Phreez:query('SELECT {author} FROM author');$a_mapper->conn()->query($sql); or: $a_mapper->conn()->select('author', 'authors'); Thanks for the feedback. Michael