EllisLab text mark
Advanced Search
1 of 8
1
   
ActiveRecord for CodeIgniter: Rails-style model interactions
Posted: 20 September 2007 09:14 AM
Avatar
Joined: 2006-05-07
270 posts

Following on from this thread, I have now got my version of ActiveRecord (based on RoR’s implementation) to a point where I’d like to get some more pairs of eyes on it.

I’ve written up the class and provided a download here:

ActiveRecord Class on the wiki

I’m using it at the moment on a project in development, and it seems to be working fine - no noticeable impact on performance or query speed, and it makes developing a lot faster without having to write CRUD functions for every single model.

In summary, it means that you can do things like this without having to write all the database interaction code yourself:

$me $this->Person->find_by_first_name('Buddy');
$me->fetch_related_pages();

$new_page = new Page();
$new_page->title 'My Title';
$new_page->content 'Blah blah blah';
$new_page->save();

$me->create_relationship($new_page); 

Note that it’s PHP5 only.

 Signature 

The Watchmaker Project | My EE add-ons | Follow me on Twitter

 
Posted: 20 September 2007 11:32 AM   [ # 1 ]   [ Rating: 0 ]
Avatar
Joined: 2007-05-30
46 posts

Really nice addition, but i’m still looking for and update and update_by method, the class only contains methods to create new records, but how you update and existing one?

Thanks again for your contribution

 Signature 

Alex Sancho
Personal Weblog
Web Studio

 
Posted: 20 September 2007 11:40 AM   [ # 2 ]   [ Rating: 0 ]
Avatar
Joined: 2006-05-07
270 posts
alexsancho - 20 September 2007 03:32 PM

Really nice addition, but i’m still looking for and update and update_by method, the class only contains methods to create new records, but how you update and existing one?

They’re on my development machine at home - I’ll update the class and the wiki when I get in to add the update method.

 Signature 

The Watchmaker Project | My EE add-ons | Follow me on Twitter

 
Posted: 20 September 2007 02:22 PM   [ # 3 ]   [ Rating: 0 ]
Avatar
Joined: 2007-07-30
2144 posts

If you want to work on merging this with Fire (I saw your reply in regards to this) feel free to do so. The code is publicly available and you are more than welcome to take it over (just give me a credit line in your readme).

 Signature 

Follow me on twitter here.
MichaelWales.com | MichaelWales.info

 
Posted: 20 September 2007 03:53 PM   [ # 4 ]   [ Rating: 0 ]
Avatar
Joined: 2006-05-07
270 posts
Buddy Bradley - 20 September 2007 03:40 PM

They’re on my development machine at home - I’ll update the class and the wiki when I get in to add the update method.

I’ve added the basic update() method to the downloadable code and the wiki article now. smile

 Signature 

The Watchmaker Project | My EE add-ons | Follow me on Twitter

 
Posted: 21 September 2007 07:54 AM   [ # 5 ]   [ Rating: 0 ]
Avatar
Joined: 2006-04-27
198 posts

Hi!

and how can I use the update() ??

like this???

$me $this->Person->get_by_id($id);
$me->fetch_related_pages();


$me->title 'New Title';
$me->content 'Blah blah blah';
$me->save(); 

edit: I forget to say wow! and thanks!!

 
Posted: 21 September 2007 08:32 AM   [ # 6 ]   [ Rating: 0 ]
Avatar
Joined: 2006-05-07
270 posts
gunter - 21 September 2007 11:54 AM

and how can I use the update() ??

Like this:

$me $this->Person->get_by_id($id);
$me->title 'New Title';
$me->content 'Blah blah blah';
$me->update(); 
 Signature 

The Watchmaker Project | My EE add-ons | Follow me on Twitter

 
Posted: 21 September 2007 02:35 PM   [ # 7 ]   [ Rating: 0 ]
Avatar
Joined: 2006-12-05
103 posts

Thanks for this nice library Buddy!

I’ll check it out!

Dan

 Signature 

FreakAuth_light: pluggable & extendable authentication library that works on CI 1.5.X

CI SWIFT MAILER: 44% less memory than PHPMailer at double speed

Using Zend Framework components in Code Igniter

 
Posted: 21 September 2007 03:17 PM   [ # 8 ]   [ Rating: 0 ]
Avatar
Joined: 2007-07-30
2144 posts

I’ve been looking over this library since it was released - this is looking really, really, nice.

Any chance of getting some better relationships involved? The relationships table you are employing (similar to RoR’s HABTM relationships) is a bit excessive for just a belongs_to or has_many relationship.

For instance:

Table: pages
id
user_id
title
body

Table: users
id
username
email

Crating a pages_users table is a bit excessive and increases the number of calls made to the database, when a relationship could simply be formed between pages.user_id and users.id columns.

I’ve yet to actually play with this library, so if it’s covered somewhere I haven’t read about yet, feel free to correct me.

Great work though - I will definitely be using this in my next project.

 Signature 

Follow me on twitter here.
MichaelWales.com | MichaelWales.info

 
Posted: 21 September 2007 05:45 PM   [ # 9 ]   [ Rating: 0 ]
Joined: 2006-10-17
207 posts

Great work, I really like it and am definitely gonna use it in my next project. I, however, need to tweak it to PHP4. At first glance this seems feasible, or is there anything exotic you used?

 
Posted: 22 September 2007 04:50 AM   [ # 10 ]   [ Rating: 0 ]
Avatar
Joined: 2006-05-07
270 posts
walesmd - 21 September 2007 07:17 PM

Any chance of getting some better relationships involved? The relationships table you are employing (similar to RoR’s HABTM relationships) is a bit excessive for just a belongs_to or has_many relationship.

You’re right (and there isn’t any other kind of relationship defined). The difficulty is that there isn’t a built-in :has_many or similar pre-defined relationship archetypes like RoR has.

Perhaps if you specify an array of relationships in the constructor of the model, something like this:

<?php

class Page extends ActiveRecord {

    
function __construct()
    
{
        parent
::ActiveRecord();
        
$this->_class_name strtolower(get_class($this));
        
$this->_table $this->_class_name 's';
        
$this->_has_one = array('author');
        
$this->_belongs_to = array('site');
        
$this->_has_and_belongs_to_many = array('resource');
        
$this->_columns $this->discover_table_columns();
    
}
    
}

?> 

And then the create_relationship() and fetch_related() functions would refer to those relationship properties when building their queries.

Does that make sense?

 Signature 

The Watchmaker Project | My EE add-ons | Follow me on Twitter

 
Posted: 22 September 2007 04:57 AM   [ # 11 ]   [ Rating: 0 ]
Avatar
Joined: 2006-05-07
270 posts
nmweb - 21 September 2007 09:45 PM

Great work, I really like it and am definitely gonna use it in my next project. I, however, need to tweak it to PHP4. At first glance this seems feasible, or is there anything exotic you used?

I’m afraid it’s impossible (AFAIK) to convert this to PHP4, due to its use of the __call() function. It catches any calls to non-existent methods, such as find_by_my_random_database_field(‘foobar’), and re-routes them to the right method - in that example, it would end up at find_by(‘my_random_database_field’, ‘foobar’). You can’t replicate that in PHP4 without creating all those find and fetch methods explicitly, which would be far too much work.

Read more about PHP5’s overloading here

 Signature 

The Watchmaker Project | My EE add-ons | Follow me on Twitter

 
Posted: 22 September 2007 05:32 AM   [ # 12 ]   [ Rating: 0 ]
Joined: 2006-10-17
207 posts
Buddy Bradley - 22 September 2007 08:57 AM
nmweb - 21 September 2007 09:45 PM

Great work, I really like it and am definitely gonna use it in my next project. I, however, need to tweak it to PHP4. At first glance this seems feasible, or is there anything exotic you used?

I’m afraid it’s impossible (AFAIK) to convert this to PHP4, due to its use of the __call() function. It catches any calls to non-existent methods, such as find_by_my_random_database_field(‘foobar’), and re-routes them to the right method - in that example, it would end up at find_by(‘my_random_database_field’, ‘foobar’). You can’t replicate that in PHP4 without creating all those find and fetch methods explicitly, which would be far too much work.

Read more about PHP5’s overloading here

Thanks but the problem fixed itself on my side. My host is about to move me to the php5 server. I indeed was afraid the __call() would be problematic.

 
Posted: 22 September 2007 06:14 AM   [ # 13 ]   [ Rating: 0 ]
Avatar
Joined: 2006-12-05
103 posts

About relationships:

Why don’t go for some conventions a bit like in CakePHP?

For example, if in the table “users” we have a field “group_id”, the foreign key for our hasMany relationship is “foreign-key-table-name_id”.

Just an idea…

Dan

 Signature 

FreakAuth_light: pluggable & extendable authentication library that works on CI 1.5.X

CI SWIFT MAILER: 44% less memory than PHPMailer at double speed

Using Zend Framework components in Code Igniter

 
Posted: 23 September 2007 04:35 AM   [ # 14 ]   [ Rating: 0 ]
Avatar
Joined: 2006-04-27
198 posts

I have a sunday question:

$data['all_boxes'$this->Box->find_all_by_project($id); 
$this->load->view('box_index',$data); 

Now I am getting 18 rows from the db
but in the profiler I see that I have 18 queries: SHOW COLUMNS FROM box

I donĀ“t believe that this makes a big performance problem, but it makes the profiler query section a lot more unreadable…
so, how can I make it that $this->_columns = $this->discover_table_columns(); only sends the first time the query and then using a global variable or something like that…

oh, in this moment I get it!  LOL I can declare the colums by hand in the model with

$this->_columns = array ('this','that'

...
...but for development it would be nice to use discover_table_columns(); (only once) - so, has anyone an idea?

 
Posted: 23 September 2007 08:18 AM   [ # 15 ]   [ Rating: 0 ]
Avatar
Joined: 2006-05-07
270 posts
gunter - 23 September 2007 08:35 AM

...but for development it would be nice to use discover_table_columns(); (only once) - so, has anyone an idea?

I never use the query profiler so I don’t notice stuff like that, but you’re right - it should be reduced to only one query if a whole bunch of rows are being returned.

Perhaps there should be a $table_columns array created in the constructor of the controller, and then when discover_table_columns() runs the first time, it adds an entry into the array:

$table_columns['Box'$query->row_array(); 

And then subsequent calls check for the existence of that array key.

Hmmm…

 Signature 

The Watchmaker Project | My EE add-ons | Follow me on Twitter

 
1 of 8
1