EllisLab text mark
Advanced Search
1 of 4
1
   
RapidDataMapper, a new Object-Relational-Mapper
Posted: 13 December 2009 09:24 PM
Avatar
Joined: 2006-08-03
671 posts

RapidDataMapper

I’ve finally managed to get my new Object-Relational-Mapper to a stage where I can release it to the public. It has taken a long time, but finally I also have a complete? manual ready (over 26k words, it was a bit of a pain to write).

RapidDataMapper is both a stand alone Object-Relational-Mapper and a mapper which can be integrated into different frameworks. I have made it CodeIgniter-compatible as a first step, but other frameworks will also follow (when I or someone else has time to create compatibility files, making it officially compatible).

The CodeIgniter specific variant replaces the $this->db object with the main connection object of RapidDataMapper, this to make it easier to use. But you can also skip replacing it (by modding the supplied MY_Loader.php) if you want to be able to use both simultaneously.

RapidDataMapper is based on the DataMapper pattern, and I have taken this to the “extreme” by completely decoupling the objects from the mapper and hiding the mappers behind a proxy object. Compared to IgnitedRecord (my previous ORM), RapidDataMapper does not affect the model, at all. Instead the model is supposed to do what it always has done: fetching and storing data. RapidDataMapper is a tool which is to be used *by* the model to simplify database interaction (it is not strictly so, you can use it in the controller or even in the view, but it “makes more sense” to place all db interaction in a few select files).

A somewhat new idea which I use in RapidDataMapper is the Descriptors. They are objects which describe how the objects should be mapped to the database, which columns that map to properties etc. They can be extended and modified in innumerable ways, making it possible to create your own defaults and override normal behaviour of the mappers.

RapidDataMapper uses an autoloader to load the files, and they are stored in the directory application/data_model/ with the name of the class + .php.

Example usage:

// application/data_model/user_obj.php
<?php
class User_obj
{
    
public $name;
    public 
$id;
}

// application/data_model/user_objdescriptor.php
class User_objDescriptor extends Db_Descriptor
{
    
function __construct()
    
{
         $this
->setClass('User_obj');
         
$this->setSingular('user'); // this makes the other default adjust themselves, eg. table becomes users

         
$this->add($this->newPrimaryKey('id'));
         
$this->add($this->newColumn('name'));
    
}
}

// Usage:

$u = new User_obj();    // the User_obj class is autoloaded

$u->name 'Martin';

Db::save($u);    // here is the "magic" done

echo $u->id;

$u Db::find('User_obj'1);

echo 
$u->name

That was just a very very simple example of the usage of RapidDataMapper, it is capable of a lot more.

RapidDataMapper is extremely configurable but it is still aimed to be easy: It assumes a lot of defaults but you can replace almost any of them. By using a code builder and mapper cache can RapidDataMapper really be rapid: only a few files needs to be loaded once the mapper has been built.

Suggestions and comments are extremely welcome!
(and I’m happy to help people start with it, but check the manual first, it should cover the most of it)

Link: http://www.rapiddatamapper.com

 Signature 

RapidDataMapper: My new ORM, is now released!

IgnitedRecord: Old ORM

MPTtree: A model to handle trees in a database.

YAYParser - Yet Another YAML Parser

 
Posted: 14 December 2009 05:12 AM   [ # 1 ]   [ Rating: 0 ]
Joined: 2009-12-11
49 posts

Yay!

First to comment!

If Rapid Datamapper makes it big, my name will be in the hall of fame.

Now, lets go test this shiny new library out.

 
Posted: 14 December 2009 09:42 PM   [ # 2 ]   [ Rating: 0 ]
Avatar
Joined: 2008-03-28
430 posts

Wow!
You really put alot of work into this!

I have’nt been able to try it, but I read the docs and it looks awesome!

Good work!

 Signature 

———————————————————————————————————————————-
Imac 27” Core i7 / 12GB RAM
Macbook Pro 15” C2D 2.53Ghz / 4GB RAM / NVIDIA GeForce 9400M + 9600M GT 512MB
iPhone 4 16Gb Black

http://www.rockkarusellen.se

 
Posted: 15 December 2009 12:40 AM   [ # 3 ]   [ Rating: 0 ]
Avatar
Joined: 2008-12-04
179 posts

Just had a go and this looks REALLLY nice. Great work! Just wondering why you chose to create a new folder called data_model and not put the models in the models folder? And on the same note not use the system/cache folder to cache the models too?

Is that because you want it to not be codeigniter specific? Perhpas in that case you could add some configuration settings that would allow you to set the path to those locations.

 
Posted: 15 December 2009 12:49 AM   [ # 4 ]   [ Rating: 0 ]
Avatar
Joined: 2008-12-04
179 posts

Also noticed that the autoload doesn’t seem to work when you do a find(). For example


This autoloads the track model and descriptor

$t = new Track(); 

However using this line doesn’t trigger the autoload

$tracks Db::find('track'); 

I get the following error

Fatal error:  Uncaught exception 'Db_DescriptorException' with message 'RapidDataMapper: Descriptor for class "track": Descriptor is missing.' in /Applications/MAMP/htdocs/CodeIgniter_1.7.2/system/application/libraries/Db.php:364
Stack trace
:
#0 /Applications/MAMP/htdocs/CodeIgniter_1.7.2/system/application/libraries/Db.php(397): Db::getDescriptor('track')
#1 /Applications/MAMP/htdocs/CodeIgniter_1.7.2/system/application/libraries/Db.php(494): Db::getMapper('track')
#2 /Applications/MAMP/htdocs/CodeIgniter_1.7.2/system/application/controllers/welcome.php(16): Db::find('track')
#3 /Applications/MAMP/htdocs/CodeIgniter_1.7.2/system/codeigniter/CodeIgniter.php(236): Welcome->index()
#4 /Applications/MAMP/htdocs/CodeIgniter_1.7.2/index.php(115): require_once('/Applications/M...')
#5 {main}
  
thrown in /Applications/MAMP/htdocs/CodeIgniter_1.7.2/system/application/libraries/Db.php on line 364 
 
Posted: 15 December 2009 01:34 AM   [ # 5 ]   [ Rating: 0 ]
Avatar
Joined: 2008-12-04
179 posts

I like this alot. I’m one of your die hard ignitedrecord fans. Obviously I understand the benefits of the separation of the object model from the interaction methods, and I especially like the fact that you have abstracted this one step further (away from codeigniter). However I have become quite attached to the methods and code names that are used by both codeigniter active record and also ignitedrecord. Why have you chosen to change little things like ‘order_by’ to ‘orderBy’?

Also would be keen to see some tests to compare Ignitedrecord vs RDM in both speed and memory!

Anyway sorry to blab on! Once again great work!

 
Posted: 15 December 2009 05:38 AM   [ # 6 ]   [ Rating: 0 ]
Avatar
Joined: 2006-08-03
671 posts

@All:

Thanks for the appreciation!

@helmutbjorg:

First: The data objects are not models, they are usually just data containers with some convenience methods for application specific tasks, eg. generating an image path.
But you can make them into whatever you like (you can even make them into some kind of ActiveRecord-ish data object, but that might not really be optimal raspberry ).

So the reason they aren’t stored in app/models is that they do not behave like CI models. Unless you make them so, but that would require a lot of unnecessary code compared to when you just have create a normal CI model which uses the data objects.

Second: And the reason I use an app specific mapper cache: What would happen if you share the mapper cache between two apps and they have different settings for the same class name?

Third: The reason you get that error is because RapidDataMapper cannot find the descriptor, it may be because the CI specific autoloader (MY_Loader::load_data_object, added in My_Loader::initRDM) is not loaded (or it can also be so that the class name is not correctly spelled (and the filename should be lowercase, but that won’t matter on mac)).

Four: The reason I changed from underscore_separated_methods to camelCaseMethods is that a lot of other PHP projects prefer to use camelCase. I still use underscore_separated_variable_names, but that is only internally in the classes. Another reason is that it requires less keystrokes to write.

 Signature 

RapidDataMapper: My new ORM, is now released!

IgnitedRecord: Old ORM

MPTtree: A model to handle trees in a database.

YAYParser - Yet Another YAML Parser

 
Posted: 15 December 2009 01:42 PM   [ # 7 ]   [ Rating: 0 ]
Avatar
Joined: 2006-08-03
671 posts

About the models, I’ve written about an alternative to CI’s models if you don’t want to use them while using RapidDataMapper.

The post can be found here: http://www.rapiddatamapper.com/#blog

And about that performance comparison, what type of tests do you want me to do?

 Signature 

RapidDataMapper: My new ORM, is now released!

IgnitedRecord: Old ORM

MPTtree: A model to handle trees in a database.

YAYParser - Yet Another YAML Parser

 
Posted: 17 December 2009 03:07 PM   [ # 8 ]   [ Rating: 0 ]
Avatar
Joined: 2006-08-03
671 posts

Has anyone tested RapidDataMapper with a somewhat advanced configuration (ie. more than one mapped class)?
(Just curious, and no, I haven’t found a fatal flaw raspberry)

Or is it that:

a) Everyone is preparing for Christmas?
b) My library is missing a feature you must have?
c) The manual is too large?
d) The manual sucks?

PS.
@helmutbjorg:

Did you get it to work?

 Signature 

RapidDataMapper: My new ORM, is now released!

IgnitedRecord: Old ORM

MPTtree: A model to handle trees in a database.

YAYParser - Yet Another YAML Parser

 
Posted: 17 December 2009 03:22 PM   [ # 9 ]   [ Rating: 0 ]
Avatar
Joined: 2008-12-04
179 posts

Yeah just been really busy (and the snow was calling me too) but I did have another play around with it. I found I was rebuilding the functionality of Ignitedrecord using RDM. Is that the idea? Do I create a model that interacts with the data model on top of RDM? You mentioned on your website that you have not yet finished implementing all of the features. I’m keen to see your todo list..

Nope I didn’t fix that error.

I put the ‘track’ model and the ‘trackDescriptor’ all in the one file ‘track.php’ and put it in the ‘data_model’ folder. I then tried to put the trackDescription into its own file ‘trackDescriptor.php’ in the same folder and that didn’t fix the problem. I guess i’m not perfectly clear (even from your examples in the manual) on exactly what files to create and where to put them. You say what to put in them but not where and how.

 
Posted: 17 December 2009 03:47 PM   [ # 10 ]   [ Rating: 0 ]
Avatar
Joined: 2006-08-03
671 posts

The idea, at least this is how I have used RDM, is that I create a “method lib” which is the model.
This method lib contains a lot of the common operations (eg. get all artworks + their users + a cover image and make sure that it is active) which I use throughout my app, some of them perform queries and return the result, others return a query object which already has some data in it and to which I can add extra conditions (for edge cases) and eg. pagination.

I guess many used IgnitedRecord just as it was and wrote the lot of the queries in the model?
(Instead of adding new methods to the class inheriting from IgnitedRecord)
You can do that with RDM too, just use Db::find(‘classname’) and then you have a query object you can manipulate.

So, to help with your error:

* Have you added the supplied MY_Loader.php?
* If you use a case sensitive system (Linux, Unix and the like (not mac OS X, strange enough)), then make sure that the files are all lowercase (in app/data_model).
* Have you called either MY_Loader::initRDM() or $this->load->database() (after adding the MY_Loader) before you try to load anything RDM related (like the descriptor or the class in data_model)?
* A note about putting them in the same class: That will work as long as you *always* try to load the Track class before the descriptor.

PS. I’ve added a vote about which upcoming feature that is most important in the feature requests section in the RDM forum here: here.

Of course, if you have another suggestion, either post it here or in RDM forum’s Feature Requests section.

 Signature 

RapidDataMapper: My new ORM, is now released!

IgnitedRecord: Old ORM

MPTtree: A model to handle trees in a database.

YAYParser - Yet Another YAML Parser

 
Posted: 17 December 2009 03:59 PM   [ # 11 ]   [ Rating: 0 ]
Avatar
Joined: 2008-12-04
179 posts

Ahhh… you hit it with ‘make sure that the files are all lowercase’. I’ll have a bit more of a play around with this tomorrow! Better get some work done right now.

 
Posted: 17 December 2009 04:02 PM   [ # 12 ]   [ Rating: 0 ]
Avatar
Joined: 2006-08-03
671 posts

Ok, good smile

I’m making that a warning then, it was written in the manual, but apparently it is buried beneath all the text raspberry.
(It will have a nice little header saying Warning before the paragraph, located in both sections dealing with CI wink )

 Signature 

RapidDataMapper: My new ORM, is now released!

IgnitedRecord: Old ORM

MPTtree: A model to handle trees in a database.

YAYParser - Yet Another YAML Parser

 
Posted: 17 December 2009 04:54 PM   [ # 13 ]   [ Rating: 0 ]
Avatar
Joined: 2007-03-10
451 posts

Hi m4rw3r,

I read the manual and love your approach. However, I’m already building 2 systems on top of a self-written ORM (probably very much inferior to yours) which was inspired in part by IgnitedRecord.
I’ll probably switch to RapidDataMapper on my next project though as especially like the seperation of object & logic. I’ll let you know my experiences when I’ve done some real stuff with it, but that won’t be for another 2 months.

I might give it an early try if I get round to rewriting my own business’s administration software - which I wrote in a hurry about a year ago when I needed it and still has a lot of db usage in the controllers. I’ll let you know any experiences I have.

Regards & complements on the library!

Jelmer

 Signature 

Starting with CodeIgniter setup
Senior dev of FuelPHP

 
Posted: 17 December 2009 04:57 PM   [ # 14 ]   [ Rating: 0 ]
Joined: 2009-12-11
49 posts

For me, I think the library packs a lot of punch but is kinda complicated and so will need some time for people to wrap their heads around.

 
Posted: 17 December 2009 05:19 PM   [ # 15 ]   [ Rating: 0 ]
Avatar
Joined: 2006-08-03
671 posts

I can agree that it might be a bit complicated at first.
I think it is mainly because you have to separate data, fetching logic, data description and data logic from each other. But because I have written it I might perceive it a bit differently.

Maybe I should try to write some quick start guide for CI? (and maybe provide an example app?)

 Signature 

RapidDataMapper: My new ORM, is now released!

IgnitedRecord: Old ORM

MPTtree: A model to handle trees in a database.

YAYParser - Yet Another YAML Parser

 
1 of 4
1