CodeIgniter Forums
DataMapper 1.6.0 - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Archived Discussions (https://forum.codeigniter.com/forumdisplay.php?fid=20)
+--- Forum: Archived Libraries & Helpers (https://forum.codeigniter.com/forumdisplay.php?fid=22)
+--- Thread: DataMapper 1.6.0 (/showthread.php?tid=11358)



DataMapper 1.6.0 - El Forum - 10-07-2008

[eluser]r2b2_kvr[/eluser]
I've been following this thread and reading along (but havent take the plunge to DM yet). This is really a great tool to simplify daily CRUD functionalities a coder always encounters Smile Also thanks a lot for actively participating and patiently answering everyone's question .. Keep it up!


I have some concerns though..
In our database we have 300+ tables so creating join tables will definitely double its size (600+ !),, do you also plan to support tables that uses foreign keys instead of table joins?

DM is quite similar to Rails' Active Record,although in AR if you have legacy tables you can specify the table name and the primary key of the those legacy tables without having to alter the table itself. It would be great if DM can have this functionality- do you also plan to do this?

Thanks a lot!

r2


DataMapper 1.6.0 - El Forum - 10-07-2008

[eluser]stensi[/eluser]
Thanks r2 :-) I know how frustrating it can be to start using a library but having little support on how to use it, so if I have time spare to help, I will.

I thought Paul's 60 tables was a lot... but 300, lol!

At the moment I have no plans to support foreign keys but that doesn't mean I wont look at including it down the road. I expect I'll get around to it eventually as I've had enough people ask for it.

Right now I'm finishing off the ability to have table prefixing, and the documentation to accompany it, as well as documenting some of my other libraries for release. I've got quite a few sitting around that should be useful to others, although some of them will take me a while to finalise.

I'll see if I can include the ability to rename the primary key ("id" field), for those with legacy tables, while finishing off the table prefixing. It should use the same premise.


DataMapper 1.6.0 - El Forum - 10-07-2008

[eluser]Maxximus[/eluser]
Cool stensi, good to see you are really active with this. I hope you consider transforming this to a library, and PHP5 it all the way, and saves some E_STRICT warnings.

Besides that, could you add count(*) (with an alias) to the options? Can be handy for the order_by. Thanks!


DataMapper 1.6.0 - El Forum - 10-08-2008

[eluser]stensi[/eluser]
@Maxxiumus: I'd actually meant to include a count() method in the past couple of versions (including the latest) but it keeps slipping my mind, lol!

I'm not sure about making it a library just yet. I can see some benefits, such as being able to autoload settings from a config file straight in but other than that, I haven't thought up a real reason to switch. Convince me why you think it would be better as a library and I'll consider it Wink


Version 1.3.4 has been released!

View the Change Log to see what's changed.

In short, table prefixing is now possible, including the ability to give joining tables a different prefix (read Setting up Table Prefixes for more information). Autoloading of classes has been improved so it plays nice with other autoloading PHP5 libraries. Also, it now performs a recursive search of the models directory, if the class being auto-loaded is not found in the models directory. This means you can sort your classes into sub-directories inside the models directory if desired.

There's a few other changes and improvements as well.

Enjoy :-)


DataMapper 1.6.0 - El Forum - 10-08-2008

[eluser]wiredesignz[/eluser]
DM should be a library for many reasons, the first being that CI's Model class is a waste of space really and has nothing to offer us other than re-assigning the CI controller libraries to a new object, the CI model may as well be another controller.

DM is a fine replacement for the CI model class, but because it is never instantiated alone and it cannot really be a defined as a model.

In fact the CI method of loading models suits datamapper better as a library than you have at present. I'll add more on this subject later. But in the meantime stensi, keep up the fine work.


DataMapper 1.6.0 - El Forum - 10-08-2008

[eluser]Paul Apostol[/eluser]
@stensi thank you very much, you're THE BEST


DataMapper 1.6.0 - El Forum - 10-08-2008

[eluser]OverZealous[/eluser]
Wow - I'm very impressed with how much you've done with a very small file (and simple setup/upgrades).

I'm still working on creating my application, but I've come across a few things I needed to modify that made DataMapper much more useful:

Code:
/**
* Get Once
*
* Gets this object if it hasn't already been gotten.
* Very useful for relationships.
*
* @access public
* @returns $this
*/
function get_once() {
    if( empty($this->id)) {
        $this->get();
    }
    $return $this;
}

// --------------------------------------------------------------------

/**
* Get By Id
*
* Gets an object by id.
*
* @access public
* @param int id of object
* @returns $this
*/
function get_by_id($id) {
    $this->where('id', $id);
    return $this->get();
}

// --------------------------------------------------------------------

/**
* is
*
* Checks to see if a field is true.
* Automatically corrects PostGreSQL Booleans
*
* @access public
* @param string the field name
* @returns $this
*/
function is($field) {
    $value = FALSE;
    if(! empty($this->{$field})) {
        $value = $this->{$field};
        if(! is_bool($value)) {
            $value = ($value == 't');
        }
    }
    return $value;
}
    
// --------------------------------------------------------------------

/**
* isnot
*
* Checks to see if a field is false.
* Automatically corrects PostGreSQL Booleans
*
* @access public
* @param string the field name
* @returns $this
*/
function isnot($field) {
    return !($this->is($field));
}

For now, I've added them to a subclass, which I'm then subclassing for my models. I don't know how useful they are for you, but you might want to add them (at least, the get_once and get_by_id methods). The other two are nice for helping with PostGreSQL Booleans, which return 't' or 'f'. They read nicely:
Code:
$user->is('admin')

Also, I have a concern with the save() function on new records. Right now it loads the id in by matching all columns. However, I can already see in a complicated system where the two objects might share the exact same information (such as two different users storing the same piece of information in the database). In this case, the returned id may or may not be the correct one.

Instead, it might be wise to use the provided $this->db->insert_id() method. This should work well, especially if used within a transaction.

Finally, is there any built-in support for transations? Or do I just need to wrap the DataMapper models in a transation?

NOTE: These functions have not been thoroughly tested yet, use at your own risk!


DataMapper 1.6.0 - El Forum - 10-08-2008

[eluser]OverZealous[/eluser]
One more question. I sometimes have additional information, such as which contact out of a list is "primary", that must be stored within the relationship.

A better example:

Tasks have many Users
Users have many Tasks
Each Task has a primary User

Is there any clean way to store this within a DataMapper setup? (Meaning, I don't want an extra relationship with an extra subclass of Users just to store which user is primary.) Normally, I would include a boolean on the joining table.

- Phil DeJarnett


DataMapper 1.6.0 - El Forum - 10-09-2008

[eluser]stensi[/eluser]
Thanks Phil. I can see where those is and is_not methods would come in handy for those using PostgreSQL. I'm a MySQL and Microsoft SQL user so never realised PostgreSQL stored Booleans that way. Almost like it's a MySQL ENUM.

If possible, I'll see if there's a way for me to detect if a PostgreSQL Database is being used, and then convert t/f fields to proper PHP Booleans so you can used them as normal, ie:

Code:
if ($u->admin) { ... }

I'm not sure about the get_once method. What situation would you need to use that in? I use the DataMapper in a way that makes sure I'm only getting once for each object I'm accessing.

I originally planned on having the get method accept an optional integer and get by id using that, but decided to make it use limit and offset instead so it would be more similar to the CodeIgniter ActiveRecord's get method. So yes, the slight downside of that is that getting by id requires a bit more code. get_by_id would be a handy addition for those who prefer to call in a simpler way, than having to specify the where clause. I'll consider putting that in the next version.

As for you last question, about the a task having a primary user, I'll have a think about it and get back to you. Been a long day Wink


DataMapper 1.6.0 - El Forum - 10-09-2008

[eluser]OverZealous[/eluser]
I'm using the get_once() in several ways. The main place I find it useful is when dealing with somewhat complex relationships.

(I've added a check to only perform the get() if the related field is not empty. This way it doesn't get run on uninitialized Models. A non-related model should already be populated!)

Say a Company has many Users. To check to see if a User can log in, I need to lookup the user's info, of course. If nothing matches, or if the User has been disabled, I can stop.

However, once I lookup the User, I also need to check to see if the Company is enabled (or has been paying their bill ;-) ). So, I do a get_once(). This way, I only load it if I need to.

After a successful login, if I need to access the Company, I can call get_once() safely, and know I'm not re-checking the database again.

Similarly, I use it when walking the object hierarchy (see below).

Since my last post, I've also come up with another simple method:
Code:
/**
* Get Clone
*
* Creates a clone of this object, and returns it
*
* @access public
* @return clone, or NULL if id has not been set
*/
function get_clone() {
    $clone = NULL;
    // try to get this object, if it is in a relationship
    $this->get_once();
    if( ! empty($this->id)) {
        $m = ucfirst($this->$model);
        $clone = new $m();
        $clone->get_by_id($this->id);
    }
    return $clone;
}

I use this for performing relationship lookups when I don't want to modify an existing object. Say I have a list of Phonenumbers for a Client. Only one of these is the default:

Code:
// in Phonenumber
function set_default()
    $c = $this->client->get_clone();
    $others = $c->phonenumber->where('default', TRUE)->get();
    foreach($others as $item) {
        $item->default = FALSE;
        $item->save();
    }
    $this->default = TRUE;
    $this->save();
}

See how it lets me nicely back-up the hierarchy and grab an ancestor. Of course, it could easily be used for going down the hierarchy, as well.

Finally, if you are interested, I have some additional validation rules that are fairly generic. I have several for parsing and comparing dates and timestamps, and one for cleaning up currency inputs (strips starting and ending non-numeric characters).

I understand being busy - thanks for working so hard on DataMapper!

- Phil DeJarnett