Welcome Guest, Not a member yet? Register   Sign In
Model Extension
#1

[eluser]BLymoth[/eluser]
Hello,
I've been using CI since 1.5, and grown to love it and use it for any quick project I'm working on. However, after working with RoR for a few months, I completely fell in love with their Active Record, and realized how lacking the built-in model class in CI is.
So I wrote this extension to enhance the functionality of CI's model, but it does not reach the full capabilities of active record (that's an understatement, I'm probably at 10-15% of active record capabilities).

Code:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

class Super_Model extends Model{
    protected $table;
    protected $schema = array();

    function Super_Model()
    {
        parent::Model();
    }

    function find($criteria=array(), $first=false)
    {
        if (is_numeric($criteria)) {
            $criteria = array('id' => $criteria);
            $first = true;
        }
        $result = $this->db->get_where($this->table, $criteria);
        return $first ? $result->row() : $result->result();
    }

    function save($record)
    {
        $record = (array) $record;
        $record = (object) array_intersect_key($record, array_fill_keys($this->schema, ''));
        
        if (isset($record->id)) {
            return $this->db->update($this->table, $record, array('id' => $record->id));
        } else {
            return $this->db->insert($this->table, $record);
        }
    }

    function destroy($record)
    {
        if (is_int($record)) {
            $record = $this->find($record);
        }
        return $this->db->delete($this->table, array('id' => $record->id));
    }
}
?>

All you have to do now, is let your models extend Super_Model, and you'll get some pretty neat functionality.

For starters, the wonderful find method. This method allows you to do something like
Code:
$this->UserModel->find()
to get an array of all available users. If you want to find a specific user you can call it by id:
Code:
$this->UserModel->find(31554)
. Of course you can fine tune your search with an array of where conditions (the syntax for CI active record 'where' method is used here).

Since we are using CI's active record implementation, we can do things like the following to extend the functionality even more(pagination for example):
Code:
$this->db->limit(5, 10);
$this->UserModel->find()

The save method allows you to pass it an array or an object, and it'll save it in the DB for you. If it is an object, and it has an attribute called 'id', then it will update the corresponding row in the database, otherwise it will insert a new row.
Another feature here is that you must define your schema in the model. And only those fields defined in your schema will be allowed to go through into the DB. This has two benefits: 1) It prevents malicious users from submitting forms with arbitrary fields. 2) It allows you to prevent the manipulation of certain fields from the application (for instance the id field).

The destroy method is quite straightforward, pass it an ID or a db object, and it'll delete the corresponding row.

Here's an example for a UserModel that extends Super_Model:
Code:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

class UserModel extends Super_Model{

    public function UserModel()
    {
        parent::Super_Model();
        //The table attribute holds the name of the table in the DB
        $this->table  = 'users';
        //The schema attribute holds the fields that are allowed to be manipulated
        $this->schema = array('username', 'email', 'password', 'salt', 'created_at', 'active');
    }
}
?>
And that's about it. Now you can start using your fancy new model and do things like:
Code:
$user = $this->UserModel->find(15);
$user->email = '[email protected]';
$this->UserModel->save($user);
$me = $this->UserModel->find(array('username' => 'blymoth'), true);
$this->UserModel->destroy($me);
$active_users = $this->UserModel->find(array('active' => 1));
$this->UserModel->destroy(32);

I'm currently working on extending Super_Model to integrate validation into it. But I thought it would be better to release the code early and get any feedback before plunging too deep into a certain direction.

Hope you enjoy it, and please, feedback!!

PS: I used the protected keyword to control access to the class attributes. This makes the extension NOT php 4 friendly.
#2

[eluser]sophistry[/eluser]
have you seen any of the ORM implementations for CI?

DataMapper and IgnitedRecord come to mind.

you might like to check those out before you round out your own project.

cheers.
#3

[eluser]mihailt[/eluser]
that's quite ok, can't say though i didn't see something simular before.
consider returning not $result->result(); but $result.
then with method chaining you can do something like this:

$this->UserModel->find(array('username' => 'blymoth'), true)->result();

not a big addition but brings you access to additional methods like num_rows() and others.

and the other thing i woudn't use array in save method consider changing it to object
and if you are creating new entry you can use stdClass to instaniate empty object




Theme © iAndrew 2016 - Forum software by © MyBB