A few months ago, I was contacted by the developer of Red Bean — a new PHP ORM library. He seems to share my dismay with the overall suckiness of every ORM library and he asked if I would give his project a looksee.
Before that, I have a few thoughts on Kohana and it’s ORM library.
Kohana
Kohana is a full-stack framework based on CodeIgniter, but ditches PHP4 compatibility for the sake of my sanity. Really, PHP4 style coding is the only reason I don’t use CakePHP for everything. But, I digress.
I’ll just start by saying Kohana is the best PHP framework I’ve used so far. I hit a few bumps in the road, but very few. It’s pretty quick (or Swift, as they would say) and is very straight-forward when it comes to extending the base functionality.
My biggest gripe about the framework as a whole, is that I ran in to limitations a lot. With the database library mostly, but with some of the other components as well. I’ve been finding that with most open source tools I’m using, that the next version, “will be way better.”
I had a major problem in the app I’m coding with session_start() sending out cache headers — overwriting what I was trying to send out manually. But, beyond that, it’s been pretty smooth sailing.
The ORM is actually pretty decent. I didn’t do any benchmarks, so I don’t know how efficient or deficient it is, but I do know that it does lazy loading on relations. That’s something I’ll just have to live with when it comes to PHP.
There are a few problems I have with it though.
- There’s no way to do aggregate functions with the Database Query Builder and adding them in seems to be a low priority. (But the next version might be AWESOME!)
- There’s no way (that I know of) to wrap a database query() result with an ORM class.
- There are some limitations in using a one-to-many relationship with a foreign key not having part of the referenced table name in the field name. In other words, it doesn’t read from FK references, but relies on the field name — i.e., Profiles.user_id is meant to reference Users.id. But if you want to have Profiles.creator_id reference a different Users.id (say the user didn’t create their own profile), there’s no way to do that with the way model relationships are defined — again, just for one-to-many relationships.
Beyond that, it’s a pretty decent library. It’s not particularly difficult to figure out how to set up models.
Let’s steam this Bean
RedBean reminds me a bit of ADODB_Active_Record in that both are developed separately from a full-stack framework. It’s slightly similar to Kohana’s ORM, but with a few key differences, which I’ll cover shortly. RedBean also reminds me of ADODB_Active_Record in the sense that the setup and usage are better and easier than other standalone PHP ORMs by several thousand trillion times over.
Now this is going to be unfair, because to me, the pinnacle of database abstraction and object-relation mapping is still SQLAlchemy. I doubt PHP will ever have something similar, but I will always hope. At least until PHP dies.
Initialization
Right off, there’s something I don’t like. The RedBean library isn’t redbean.php — it’s oodb.php. I’m not really sure why, but I could see myself being confused by this if I used RedBean for a project. What can I say? I’m simple.
I think a lot of the naming scheme is something I’d want to be different.
RedBean_Setup::kickstartDev connects to the database and creates models. This is one of the features I like about RedBean. With ADODB_Active_Record, I have to define classes and extend, etc. RedBean creates the Models for you. Unfortunately, I can’t figure out why RedBean_Setup is it’s own class and if I had never seen documents before, I would never guess that the initialization method would be called ‘kickstartDev’. Would RedBean::connect() be too easy?
Table Creation
Another neet feature of RedBean is that it will create a database schema for any model that doesn’t already have a table. Read the docs, you’ll see it.
SQLAlchemy has something similar with Metadata().create_all(). Although with that, you create the model declaratively. RedBean will build the schema based on what fields you have set in the model. It sounds handy, but Python programmers would probably be unsettled — it’s just a different philosophy.
I didn’t have time to test this extensively, so as to what happens when you set a new field when the model is already defined, I can only speculate.
The CRUDiness
Overall, there aren’t many surprises when it comes to fetching records.
//Load a user
$user = new User($id);
//Similarly with Kohana's ORM
$user = ORM::factory('user', $id);
Kohana can also do the top syntax (i.e., new Users_Model($id)) — but the seemingly preferred way is the lower.
Inserting/Updating a row is done via Model::save(), as is the case with almost all Active Record implementations.
Fields can be accessed using properties: $object->field, or using getters and setters (blah): $object->getField();
Deleting is somewhat inconsistent.
//Delete user User::delete($user); //I would think this is more readable/consistent: $user->delete();
But it’s not a big deal.
Other Things
There are two cool functions that I think every ORM should consider — import and export. Import will set field values based on an array, and export will serialize the row to an array (note: Kohana has this too). An extension of import() is provided as importFromPost — which sure beats setting field names manually from forms.
One last thing…
RedBean has a “Locking” feature that I’ve been trying to figure out. No, I know what Locking is, but I’m just wondering why it would be necessary? A modern, transactional database is not going to have problems with multiple users. Even SQLite supports basic mutli-user functionality. Maybe someone can explain this to me?
Well, that’s about all I can think to say. There may never be a perfect ORM for PHP, but some are better than others. Based on API and not on performance, I can say in my biased, unfair, ridiculous opinion, that RedBean is better than most.
If I have a project that I might be able to use RedBean with, I’ll definitely give it a shot. So there may be a second review in the future. Who knows?
To Gabor de Mooij, RedBean’s author:
Good luck with the project — hopefully RedBean destroys Propel. :)
Perhaps you could take a look at PHP-activerecord sometime if you get a chance:
http://www.phpactiverecord.org/
It is an ORM based on Ruby on Rails’ ActiveRecord. The 3rd problem you found with Kohana is not an issue with our library. Please let me know what you think. We’ve done some performance profiling and have seen superior speeds to doctrine/propel, but we haven’t included them yet on our project.
That looks pretty cool — although I don’t have PHP 5.3 on any of my machines, so it’ll be pretty tough to test. I should probably just get off my lazy ass and quit running xampp on my work box.