CodeIgniter Forums

Full Version: ActiveRecord library - one to one solution proposal
You're currently viewing a stripped down version of our content. View the full version with proper formatting.

El Forum

[eluser]esbium[/eluser]
Coming from a Java world where we have things like Hibernate for ORM, I have taken the persistence layer for granted for a while now. I recently started developing a php app on CI and found the ActiveRecord library in the Wiki. Its great and its probably only going to get better. One thing I found that I don't like though is that it only supports 1-1 relationships with a pivot table.

I developed an extension to that library to handle normalized 1-1 relationships and thought I would post it here to get feedback, ideas, etc. This is just the start of it and I have only tested it with a few relationships. They seem to work though.

Keep in mind while reading this post that I have been a Java developer for years but just recently started working with PHP professionally. It has been a hobby for a few years though. If you see mistakes in my code, please don't hesitate to point them out!

Enough chatter! Here is the __call function in the ActiveRecordEnhanced class:

Code:
public function __call($method, $args)
{
    if(stristr($method, 'fetch_1to1_')) return    $this->_fetch_one_to_one(str_replace('fetch_1to1_', '', $method), $args);
    //if not one of our new methods, call the original
    return parent::__call($method, $args);
}

And here is the private _fetch_one_to_one function:
Code:
private function _fetch_one_to_one($oneToOneTable, $args)
{
        //TODO this will break for person/people etc..  Find a way to load the other model and get its _table attribute, maybe...
        $relationshipTable = $oneToOneTable . 's';    
        
        $query = $this->db->query('
            SELECT
                ' . $relationshipTable . '.*
            FROM
                ' . $relationshipTable . '            
            WHERE
                ' . $relationshipTable . '.id = ' . eval('return $this->' . $oneToOneTable . '_id;')
        );        
        eval('$this->' . $oneToOneTable . ' = $query->row();');    
        //TODO, what do we do if it returns no results?
        if(empty($this->$oneToOneTable))
            $this->$oneToOneTable = new stdClass();
}

So, given a data relationship like Task -> Project, meaning each Task has a parent Project, and the Task table has a column like 'project_id', I can now write code like this:
Code:
$task = $this->load->model('task');
$tasks = $this->task->find(ALL);
foreach($tasks as $tsk)
{
    echo "Task name = " . $tsk->name . '<br/>';
    //load the parent project
    $tsk->fetch_1to1_project();
    echo 'Parent Project name: ' . $tsk->project->name;
}

What does the CI community think? Am I on the right track? Also, am I duplicating efforts? I don't want to use ORM solutions like Propel or Doctrine, I have my reasons.

Let me know!!

El Forum

[eluser]Crafter[/eluser]
I noticed just yesterday that the WIKI has an activerecord library contributed. You may want to compare notes with that initiative.

El Forum

[eluser]Piinaaja[/eluser]
[quote author="Crafter" date="1191121754"]I noticed just yesterday that the WIKI has an activerecord library contributed. You may want to compare notes with that initiative.[/quote]

Well, didn't he just state that "... found the ActiveRecord library in the Wiki"?

The ActiveRecord library in the wiki just doesn't fully cut it, it has very limited support for one-to-one or one-to-many relations. Creating a join table for many-to-many relations is sensible, but requiring it for one-to-one or one-to-many isn't really effective.

I think it's great you're sharing your changes to that functionality, it would be great to have a fully functional, Rails like ActiveRecord class for CodeIgniter.

El Forum

[eluser]Crafter[/eluser]
Quote: Well, didn’t he just state that “… found the ActiveRecord library in the Wiki”?
Oopsee

Quote:The ActiveRecord library in the wiki just doesn’t fully cut it,
Agree. That will prevent me from adopting this library just yet. But I'm not a fan of the official CI Activerecord implementation myself.

There was some talk of an update of the CI ActiveRecord library. Dates and roadmap - well - that's another thing in the CI domain!

I'm been using a moddified version of the MyActiveRecord library for some of my projects. It has decent relationship handling, but there are some issues that prevent a proper implementation.

El Forum

[eluser]Matthew Pennell[/eluser]
[quote author="Piinaaja" date="1191124736"]The ActiveRecord library in the wiki just doesn't fully cut it, it has very limited support for one-to-one or one-to-many relations. Creating a join table for many-to-many relations is sensible, but requiring it for one-to-one or one-to-many isn't really effective.[/quote]

I created the ActiveRecord library; I know that its relationship mapping isn't perfect at the moment, and there have been some discussions on the thread in Ignited Code on how to improve it in that respect. I'm in the middle of a big project at the moment, but once that's out of the way, I'll be looking at addressing your concerns. Smile

El Forum

[eluser]Crafter[/eluser]
Quote:I created the ActiveRecord library; I know that its relationship mapping isn’t perfect at the moment,...

Well I think its a wonderful contribution to address very serious demands from CI users. Well done on the work so far.

Granted that there are issues, but perhaps it's threads like this that allow you to develop a raodmap for the producst and get input from other users and early adopters. I'm sure we can pull through together to create an implementation that works for all of us.

El Forum

[eluser]Piinaaja[/eluser]
[quote author="Buddy Bradley" date="1191152613"]
I created the ActiveRecord library; I know that its relationship mapping isn't perfect at the moment, and there have been some discussions on the thread in Ignited Code on how to improve it in that respect. I'm in the middle of a big project at the moment, but once that's out of the way, I'll be looking at addressing your concerns. Smile[/quote]

Hey Buddy, great to see you participating in this discussion. I didn't mean to disrespect your contributions in any way, I think it's a great work so far and it's nice to hear that you're going to further develop your library in the future.

El Forum

[eluser]esbium[/eluser]
Buddy,

Thanks for the ActiveRecord class (and anyone else who worked on it)! I have spent the last couple of days really reading and understanding the source code and I have some new ideas that I would like to share over the course of the next few weeks.

As I mentioned, I come from a java background and have been using Hibernate for a while now. In Hibernate, and other java ORM libraries, one can get child objects like so:

Code:
//JAVA Code - is this kind of code allowed on the CI forums? (lol)  ;-)
Project project = projectDao.findById(1);
for(Task task : project.getTasks())
{
    //do something with the task object here...
}

I have grown used to this and love how it works. Hibernate takes care of lazy loading the tasks once getTasks is called. This works after minimal configuration of course!

With that said, I have set out to build something similar on top of your ActiveRecord class by extending it and adding the functionality I want. I have the above example working with minimal configuration and its great! I will post the code once I have more to share, should be soon as I am developing this for a project I am consulting on right now.