Just what is a "Model" supposed to be in CI?

#1
[eluser]Chrisbloom7[/eluser]
I've been developing with PHP for going on 7 years now. About a year ago I started to dabble with Ruby on Rails, and though I liked the idea of the framework and what it could do, I was not at all comfortable with the Ruby language itself nor with some of the limitations that "convention over configuration" imposed, so I came back to PHP. I'm now playing around with CI as it seems to give me a lot of the useful features that I really enjoyed in Rails and with a very minimal code base.

One question I have at the moment is what is a "Model" to CI? Technically, a model is a representation of some data object, like a user, a blog post, a car, etc. However, of all of the examples that I've seen in the video tutorials and in the CI documentation a model is treated more like a container for some helper functions - there is no OO programming going on.

Ideally, I would like my models to be ORMed so that I could create an instance of a model and work on it directly, as well as add in validation, getters and setters, and other abstracted functions. As I understand it now, the only way to do access data in CI is to use the Database class to grab the data from the database, but the data itself (from the result() function) is an array, not an object. Even the supplied Active Record class doesn't really have anything to do with OO at all. It appears to be just another database abstraction layer.

Am I missing something that I could be doing to reach this result? Or am I misunderstanding what CI is using models for?

It seems like the real way to go might be to extend the Database class for each object I want to model, but then what do I lose out on if I'm not using the Model class? And how to I load my new Database classes?

#2
[eluser]überfuzz[/eluser]
First of all, 'OOP' isn't the solution to everything, when it comes to the web. In some cases, maybe even most cases your website is doing just dandy with ordinary code, or what you would like to call it. If you want to get a grip on objects I suggest that you try to build something where you'll really need object. (Or that is it could be done without object orientated programs but objects will make it much easier.)

I programmed a planetary system during my education. See if you can spot any objects there, take a wild guess. ;-P I seem to recall that a tricky part was programming the movement, that would be, translating the function into java, c++, php or what have you.

#3
[eluser]Yorick Peterse[/eluser]
I'm not an expert when it comes to the theoretical part of OOP and the MVC structure. As far as I understand Controllers are your main "things", they load the models and views, perhaps do some validation etc. The models are being used to work with data retrieved from a database. The views simply display the results.

For example you would have an index() function that calls a model which will fetch all users:

Controller
Code:
<?php
controller Test extends Controller {
  function index() {

    //First load a model
    $this->load->model('test_model');
    
    //Execute the get_users() function that's stored inside the model and store the results into an array
    $data = array (
            'result'    => $this->test_model->get_users()            
    );

    //Load the view with the results
    $this->load->view('some_view',$data);
  }
}
?>

Controller
Code:
<?php
class Test_model extends Model {
  function get_users() {

  //Create a query
  $query = $this->db->get('users');

  //Return the results
  return $query->result();
  }
}
?>

#4
[eluser]Dam1an[/eluser]
Most people think a model is purely an interface to the database, but a model should deal with any data sources, including databases, files, APIs etc

You also get people who think business logic should be moved to the model, but I personally think that belongs in the controller

#5
[eluser]mitchwilson[/eluser]
To answer the original post, great question! The CI Model was really confusing for me at first as well, since it did not conform to my expectations based OOP.

From previous programming experience, I expect the model to be a class that I use to make instances. I expect an instance to refer to one record in the database, if I am using a database table for that model class.

Basically, I expect to write code like this and it would load each instance from the database:
Code:
// Create two instances, each would refer to each record in the friends table.
// They would not necessarily automatically connect to the database, but when
// I wanted to connect, they would already know which records they referred to.
$friend1 = new Friend('Sawyer');
$fiend2 = new Friend('Jack');

// Then be able to use each instance to call methods pulling internal information to the model.
$friend1->greet(); // Says 'My name is Sawyer, I am 30 years old.'
$friend2->greet(); // Says 'My name is Jack, I am 43 years old.'

// And I could call a setter that would update the database record for this instance.
$friend1->setAge(39);
$friend1->greet(); // Says 'My name is Sawyer, I am 39 years old.'

Ok end of dream code. That is not how CI works. In CI, a Model is really a database helper to store all your SQL as individual methods for that Model, for example.

Code:
class Friend_model extends Model {

function greet($id) {
// Fill in code to query database to get text from greeting field from friends table
}

}

Note that you need to pass in the id of the record you want. So you call it like this:

Code:
$this->load->model('Friend_model');
$this->Friend_model->greet(123);

Now that is just odd. I really love CI, but that is not OOP. After I got used to it, I'm still not keen on it, but not a big deal to do this to get more OOp on it. I am testing this technique out.

Code:
$this->load->model('Friend_model');
$friend1 = $this->Friend_model;
$friend1->init(123); // Do the extra step of creating/calling an intialize method.
$friend1->greet(); // Says 'My name is Sawyer, I am 39 years old.'

NOTE: All the above is psuedo code for discussion's sake. Some works, some won't when used literally. It's just for information discussion sake only.

Also, note that in OOP, when you initialize an new instance, you usually are creating a NEW instance. In CI, while you might be creating a new instance you are loading an existing record from the database. So using the new keyword is also confusing, even when trying to be more OOP. Using init() is less confusing but not perfect. Maybe use load()?

So, really, I haven't figured out the best technique, but I'm working on it personally. Would love to hear what others have come up with.

#6
[eluser]sl3dg3hamm3r[/eluser]
I often observed here that the term model is missunderstood with a simple DAL (data access layer). Also what Dam1an mentioned, I completely disagree. The classical MVC-Pattern states to keep the controller as light and slim as possible. In the controller, developers also often use Command, but in terms of CI, I never tried to do anything that way. For small, straight-forward projects it might become too complex I'd say, benefits are too little.

Nobody keeps you from using the Model-Layer for your business-objects, which could be completely unaware of the persistence layer. If you use an ORM, or self written Data Access Objects / Data Transfer Objects / whatever is up to you. If the business-cases become really complex, I highly recommend to go that way. I just recently finished a project with CI, which had some complex data assembling going on. I solved that with complex nested associative arrays and regretted it later on that I didn't do it the proper OOP-way with some ORM or DAOs. For me, this goes everything into the model.

#7
[eluser]wiredesignz[/eluser]
Models should encapsulate the data access layer, ORM or any other business objects needed. The most important thing to understand is that Models should not be replaced by ORM or anything else.

#8
[eluser]Chrisbloom7[/eluser]
Coming back to this a bit late...

@überfuzz - Your response was incredibly unhelpful. I'm well aware of the differences between OO versus procedural programming. (As I said, I've been doing this for over 7 years.) I've done plenty of projects where it was fine to just do a quick database query and work on a results array and be done with it, but I've had to fix an equal number of projects where lazy procedural programming led to errors and redundancy that OO would have prevented. In this case, I was asking specifically about OOP because it's what I needed.

@Yorick Peterse - Thanks for that example. I too tried to extend/overload the base Model class, in my case by using ADOdb's Active Record library, but because of the way the CI base self-references itself I kept running into an obscure PHP error having to do with the magic __get function. (see http://bugs.php.net/bug.php?id=38146). Ultimately I just had to give up on CI and move on.

@sl3dg3hamm3r - That has been my experience as well.

In all honestly, although CI has a number of useful libraries, it also has A LOT of useless cruft and shortcomings. I can think of no reason to recommend CI over building a simple MVC/ORM framework from scratch with only what you need, except perhaps if someone wasn't comfortable with OOP on their own and just needed a clean base to start with.

#9
[eluser]Chrisbloom7[/eluser]
[quote author="wiredesignz" date="1250789116"]Models should encapsulate the data access layer, ORM or any other business objects needed. The most important thing to understand is that Models should not be replaced by ORM or anything else.[/quote]

I'm certainly not saying "All you need is ORM". Some models might not need ORM, but for the majority of models that I write, I want some sort of direct data object representation with the ability to extend it with business logic. That is what is lacking in CI's model implementation.

#10
[eluser]wiredesignz[/eluser]
I'd be interested to hear what you chose as your solution. Or see how you coded your own from scratch.


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2021 MyBB Group.