Using Jamie Rumbelow's My_Model

Building forms in your app? Be sure to consider these common security mistakes: 
Web form security - avoiding common mistakes
Like PDO? Check out how to use it with Codeigniter
Codeigniter with PDO Thanks!

One thing I've noticed while answering questions one the CodeIgniter forums is how few "noobies" seem to use a MY_Model library. The concept of a MY_Controller is mentioned all the time, and more and more people are using templates libraries for their views, but MY_Model often seems to slip by.

Joost van Veen (codeigniter.tv) just released a great 4-part tutorial on building your own MY_Model (check it out here: Extending the Codeigniter core: MY_Model ), but I thought a lot of people might be scared off by how much work it takes to write their own. So, why not encourage them to learn from Joost, but in the meantime, grab a top-notch code library and start using it? After all, isn't that the point of a library?

Jamie Rumbelow's MY_Model (http://github.com/jamierumbelow/codeigniter-base-model) is probably the best-known out there. It has been contributed to by Phil Sturgeon, Dan Horrigan and Adam Jackett, and is the basis of the model used in PyroCMS, so you can count on it being well-designed. However, it is not well documented and a bit intimidating to the uninitiated.

Therefore, instead of my writing a new tutorial or library which wouldn't be as good as what these guys have already contributed, I thought I would just introduce you to Jamie's and give you lots of examples on how to get going.

So...let's get going

Setup:

1) download the library from the link above and put it in your /core directory

2) create a table with this:

CREATE TABLE IF NOT EXISTS `articles` (
 `body` text,
 `title` varchar(250) DEFAULT NULL,
 `id` int(11) NOT NULL AUTO_INCREMENT,
 PRIMARY KEY (`id`),
 FULLTEXT KEY `body` (`body`,`title`)
) ENGINE=MyISAM  


--
-- Dumping data for table `articles`
--

 INSERT INTO `articles` (`body`, `title`, `id`) VALUES
 ('bears are fuzzy and cute - but don''t try to pet them!', 'Something about bears', 1),
 ('Fuzzy Wuzzy was a bear; Fuzzy Wuzzy had no hair. Fuzzy Wuzzy wasn''t very fuzzy, was he?', 'Fuzzy Wuzzy', 2),
 ('This is dumb and boring', 'Dumb and boring post', 3),
 ('This is dumb and boring, too.', 'Dumb and boring post', 4);

 

3) create a model called article_model.php (no "s")

class Article_model extends MY_Model
{

}

4) last, make a test controller to run all your queries from. Here is a fairly complete list of all of the functions available to you, each one given by an example with the output you should expect (if you run them one at a time in order), as well as the actual sql generated. My thought is this will be all you need to get going. All of this code should go in your controller. Don't forget to start with:

$this->load->model('article_model');

 

$row = $this->article_model->get(2);		
//stdClass Object ( [body] => Fuzzy Wuzzy was a bear; Fuzzy Wuzzy had no hair. Fuzzy Wuzzy wasn't very fuzzy, was he? [title] => Fuzzy Wuzzy [id] => 2 ) 
//SELECT * FROM (`articles`) WHERE `id` = 2

$row = $this->article_model->get_by('title', 'Fuzzy Wuzzy');
//stdClass Object ( [body] => Fuzzy Wuzzy was a bear; Fuzzy Wuzzy had no hair. Fuzzy Wuzzy wasn't very fuzzy, was he? [title] => Fuzzy Wuzzy [id] => 2 ) 
//SELECT * FROM (`articles`) WHERE `title` = 'Fuzzy Wuzzy'
// NOTE: if more than 1, returns first

$result = $this->article_model->get_many(array(1,3,4));
//Array ( [0] => stdClass Object ( [body] => bears are fuzzy and cute - but don't try to pet them! [title] => Something about bears [id] => 1 ) [1] => stdClass Object ( [body] => This is dumb and boring [title] => Dumb and boring post [id] => 3 ) [2] => stdClass Object ( [body] => This is dumb and boring, too. [title] => Dumb and boring post [id] => 4 ) ) 
//SELECT * FROM (`articles`) WHERE `id` IN (1, 3, 4)  

$result = $this->article_model->get_many_by('title', 'Dumb and boring post');
//Array ( [0] => stdClass Object ( [body] => This is dumb and boring [title] => Dumb and boring post [id] => 3 ) [1] => stdClass Object ( [body] => This is dumb and boring, too. [title] => Dumb and boring post [id] => 4 ) ) 
//SELECT * FROM (`articles`) WHERE `title` = 'Dumb and boring post'

$result = $this->article_model->get_all();
//Array ( [0] => stdClass Object ( [body] => bears are fuzzy and cute - but don't try to pet them! [title] => Something about bears [id] => 1 ) [1] => stdClass Object ( [body] => Fuzzy Wuzzy was a bear; Fuzzy Wuzzy had no hair. Fuzzy Wuzzy wasn't very fuzzy, was he? [title] => Fuzzy Wuzzy [id] => 2 ) [2] => stdClass Object ( [body] => This is dumb and boring [title] => Dumb and boring post [id] => 3 ) [3] => stdClass Object ( [body] => This is dumb and boring, too. [title] => Dumb and boring post [id] => 4 ) [4] => stdClass Object ( [body] => Ain't no sunshine [title] => When she's gone [id] => 13 ) [5] => stdClass Object ( [body] => Woot! [title] => My thoughts [id] => 11 ) [6] => stdClass Object ( [body] => Hello [title] => I must be going [id] => 12 ) ) 
//SELECT * FROM (`articles`)

$count = $this->article_model->count_by('title', 'Dumb and boring post');
//2
//SELECT COUNT(*) AS `numrows` FROM (`articles`) WHERE `title` = 'Dumb and boring post'

$count = $this->article_model->count_all();
//4
//SELECT COUNT(*) AS `numrows` FROM `articles`

$insert_id = $this->article_model->insert(array('body'=>'Woot!', 'title'=>'My thoughts'), FALSE);
//5
//INSERT INTO `articles` (`body`, `title`) VALUES ('Woot!', 'My thoughts')


$insert_array = array(
		array('body'=>'Hello', 'title'=>'I must be going'),
		array('body'=>"When she's gone", 'title'=>"Ain't no sunshine" ),
	);
$insert_ids = $this->article_model->insert_many($insert_array, FALSE);	
//Array ( [0] => 16 [1] => 17 ) //1
//INSERT INTO `articles` (`body`, `title`) VALUES ('When she\'s gone', 'Ain\'t no sunshine')


$update_id = $this->article_model->update(4, array('body'=>'This is dumber and more boring', 'title'=>'Dumber and boringer'));
//1
//UPDATE `articles` SET `body` = 'This is dumber and more boring', `title` = 'Dumber and boringer' WHERE `id` = 4

$update_id = $this->article_model->update_by(array('title'=>'My thoughts'), array('body'=>'Having deeper thoughts'));
//1
//UPDATE `articles` SET `body` = 'Having deeper thoughts' WHERE `title` = 'My thoughts'	

$update_id = $this->article_model->update_many(array(3,4,5), array('body'=>"Oh! I've been updated...and I feel MARVELOUS!"));
//1
//UPDATE `articles` SET `body` = 'Oh! I\'ve been updated...and I feel MARVELOUS!' WHERE `id` IN (3, 4, 5) 	

$update_id = $this->article_model->update_all( array('title'=>"Another dumb title"));
//1
//UPDATE `articles` SET `title` = 'Another dumb title' 	

$delete_id = $this->article_model->delete( 7);
//1
//DELETE FROM `articles` WHERE `id` = 7 

$delete_id = $this->article_model->delete_by( array('body'=>'Hello'));
//1
//DELETE FROM `articles` WHERE `body` = 'Hello' 

$delete_id = $this->article_model->delete_many( array(3,4,5));
//1
//DELETE FROM `articles` WHERE `id` IN (3, 4, 5) 

//// Utilities ////

// dropdown - automatically picks the primary key if only one value passed
$dropdown_array = $this->article_model->dropdown( 'title');
//Array ( [1] => Another dumb title [2] => Another dumb title ) 
//SELECT `id`, `title` FROM (`articles`)


// otherwise, give it a key, value pair to build on (my data is bad for example at this point)
$dropdown_array = $this->article_model->dropdown( 'title', 'body');
//Array ( [Another dumb title] => Fuzzy Wuzzy was a bear; Fuzzy Wuzzy had no hair. Fuzzy Wuzzy wasn't very fuzzy, was he? ) 
//SELECT `title`, `body` FROM (`articles`)

 

Finally, a couple of common tasks you might be after (this code goes in article_model.php ):

#1 - I only want certain fields

Create a new function to make your select function call, but then stick to the parent get()

function select($fields)
{ 
        $this->db->select($fields); 
        return $row = $this->get(2); 
}

//SELECT `title` FROM (`articles`) WHERE `id` = 2

#2 - I want to validate my insert

Create all the validation rules you might need for anything on this table at the top of your class. NOTICE it is an array of arrays (check the user guide http://codeigniter.com/user_guide/libraries/form_validation.html#rulereference for rules)

protected $validate = array(array('title'=>'required'));

That should get you started down the road to happy MY_Model usage :-)  Come to the Codeigniter forums and ask if you run into trouble.



Comments

  • Mfawa Alfred Onen

    2012-01-14

    Nicely explained. To be honest I have used Jamies code and from time to time refactor it to suit my daily usage of the framework. I have also seen Joost videos and are very handy.

  • Adam Jackett

    2012-01-14

    Great article. I love this base model and still use it in every project. I added before_get and after_get methods so that you can easily do things like better selects (instead of SELECT *) and joins using before_get, and attach other data from other models using after_get. It's sort of a makeshift ORM. The only caveat is that if you're not careful, you could end up with performance issues and also infinite loops, but just be careful and you're fine. With great power comes great responsibility.

    Anyways, thanks for including me in the contributors list. :D

  • Dejan

    2012-01-19

    Hi

    Great tutorial and really handy as addition to official docs.
    I think there's a problem with this:
    "
    3) create a model called article.php (no "s")

    class Article_model extends MY_Model
    {

    }
    "
    As you can see, the model (file name) is article.php, while the class name is Article_model.

    Greetings

  • Jeff Madsen

    2012-01-19

    Thanks for the feedback guys!

    @dejan - thanks for catching that. I've fixed it now.

    @adam - yes, considered showing some extensions, decided it would be better to just demonstrate a "common library" for now. Maybe down the road.

  • Rob Allport

    2012-05-27

    One of the best CI base models around. Simple to use, underastand and keeps your models clean.

  • Ci_noob

    2012-06-15

    As far as I can tell you cant do complex joins etc with this model...is that true?

  • Jeff Madsen

    2012-06-16

    Hi Ci_noob,

    No, there is no method explicitly for doing joins, but you have two choices:

    1) Use the before_get functionality to set it, or

    2) similarly, extend the get() function on your child model, add the active record join code, then call $this->get() to trigger the parent function.

  • Ci_noob

    2012-06-16

    Jeff -

    Thanks for the reply. Anyway you can provide an example? As of now I am overly duplicating my base CRUD for each Model and I know I am going against DRY but I am just trying to finish the product...thanks for the response btw!

  • Jeff Madsen

    2012-06-18

    Hi Ci_noob,

    A couple ways to do this might be (not "real" code, just to give the idea):

    //controller
    $this->user_model->get_one(1, 'join_child');

    function get_one($id, $function)
    {
    $this->before_get = array($function);
    return $this->get($id);
    }


    function join_child()
    {
    $this->db->join('user_profiles up', 'up.user_id = users.id');
    }

    or else:

    function get_one($id)
    {
    $this->db->join('user_profiles up', 'up.user_id = users.id');
    return $this->get($id);
    }

    There's also a lot of ideas to build up a nice generic join extension, perhaps someone will care to post.

  • Cristiano Ronaldo Profile

    2012-07-03

    Thank you for any other informative website. Where else could I
    am getting that kind of information written in such
    a perfect means? I have a project that I'm just now working on, and I've been on the glance out for such information.

  • Matthew Schenker

    2012-07-08

    Thanks for a great article! I just finished reading Jamie's book, "Who Needs Ruby?" which gets into the base model step by step and your article is a nice follow up.

    One thing I am still confused about though: how to do essential CRUD actions with forms using My_model? Especially, I'm interested in how to re-populate a form for editing/updating.

    Would it be possible to do a tutorial on this subject?

    Thanks again for your great article!

  • Jeff Madsen

    2012-07-08

    Hi Matthew,

    Glad it was helpful! There is nothing in particular that makes working with a form any different than doing any other basic CRUD statements with the MY_model, unless you are thinking of validation? Can you explain a little more what you are after, and I'll see what I can throw together for you

  • Ami Creative Design

    2012-07-23

    Thanks for this. This is very well written tutorial that great when you first download the model - got me using Jamies model within 10 minutes.

    Amy

  • Matthew Schenker

    2012-08-04

    Hey Jeff, thanks for the response!

    To follow up my last post...

    Would it be possible to put together a tutorial that shows how to use my_model to actually go through the steps of creating, reviewing, updating, and editing content in a sample application like a site where people can post/edit articles?

    After reading Jamie's book, and your tutorial, I get the concept but would like to see how it all works through actual controllers and views.

    Thanks again for your tutorial!

  • Jeff Madsen

    2012-08-04

    @Matthew - there is no real difference in how you do that when using a MY_Model class. MY_Model just gives you a set of pre-defined functions so that you don't have to recreate them in each model.

    I don't really have the time nor see the necessity of another CI intro tutorial - if you are looking for something like that, let me recommend the great series on NetTuts: http://net.tutsplus.com/sessions/codeigniter-from-scratch/

  • @aageboi

    2012-08-31

    The example of validation is wrong. It should be :

    protected $validate = array(
    array(
    'field' => 'title',
    'label' => 'Title',
    'rules' => 'required'
    )
    );

  • Jeff Madsen

    2012-09-05

    @aageboi - thanks! Yeah, I've known about that for a while, but been too swamped to deal with it. Also would like a to write a Part II of this with Jamie's new additions

  • Benong

    2012-11-19

    hi,
    i understand this line code:
    $row = $this->article_model->get(2);
    //SELECT * FROM (`articles`) WHERE `id` = 2

    What is the correct code if i need to:
    //SELECT * FROM (`articles`) WHERE `username` = 'xxx' AND `password` = 'yyy'

  • Tony Dew

    2012-11-26

    @Benong: Something like this:

    $row = $this->article_model->get_by(array('username' => 'xxx', 'password' => 'yyy'));
    //SELECT * FROM (`articles`) WHERE `username` = 'xxx' AND `password` = 'yyy'

    Note: sent his from my phone and haven't tested the code, but anything the you can use with $this->db->where() should work.

  • Billie

    2012-12-20

    Hi! Great tutorial!
    Just a question... why if i use "$row = $this->article_model->get(2);" I get a simple array but in "$result = $this->article_model->get_all();" I get an object?
    In other words, the difference in the view with the foraech is:
    case 1:
    foreach ($list as $item):
    echo $item;
    case 2:
    foreach ($list as $item):
    echo $item->ID;

    How can i use $item->ID in the first case with "get()"?

    Thanks!

  • Jeff Madsen

    2012-12-26

    Hi Billie,

    Have a look in the code. You'll see get() - since it is pulling from the primary key - returns a $row array, whereas get_all() obviously wants all rows.

    Getting an array or object depends on your:

    protected $return_type = 'object';

    and can be overridden with as_array() or as_object()

    Hope that helps

  • Arun K V

    2013-08-25

    Its a great tutorial. This was really helpful. I have just created a sample application that uses my_model to create, update, delete content.
    You can find it at: https://github.com/akvgit/Article-Test

  • Joost Van Veen

    2013-09-27

    Hi Jeff, thanks for referencing my tutorial :) You're absolutely right. It is great to learn how stuff works using tutorials, and then use a solid library under active development, like Jamie's excellent MY_Model.

  • Ubel Jan Van Wijhe

    2013-10-14

    For a Dutch article about My_Model from Jamie Rumbelow go to http://codeigniter.vanwijhecons.nl/eigen_artikelen/codeigniter/my_model_een_nederlandse_uitleg
    The application can be found at http://codeigniter.vanwijhecons.nl/eigen_artikelen/codeigniter/de_applicatie_bij_my_model
    Enjoy it.
    Ubel Jan van Wijhe

  • Jk

    2013-11-14

    Hi Jeff,

    I am wondering how I can achieve selecting only particular fields with a where clause, something like the code below,
    <code>
    $this->select("some_col");
    $this->get_many_by(array("isArc"=>1));
    </code>
    I understand your #1 select function mentioned above but it has the condition tied within the function.

    Thanks,
    JK

  • Jimmy

    2013-12-18

    Hi Jeff,

    How can I use MY_Model with this query

    SELECT body, title from articles

    Thanks,
    Jimmy

  • Jimmy

    2013-12-26

    Sorry, I read too fast and was skip some important things.

    I found it.

    Great example. Thanks

  • List.ly

    2014-03-06

    I am genuinely delighted to glance at this webpage posts which carries lots
    of valuable data, thanks for providing such information.

Post a comment