Welcome Guest, Not a member yet? Register   Sign In
Modelling Questions
#1

[eluser]dreamnid[/eluser]
Hi all,

We want to rewrite our codebase from scratch using CI. However, I'm trying to figure out how to model our code into something that will work with CI.

Here is what I'm trying to do (written in Java):

Code:
public class Person {
   private int id;
   private String name;
   private String pass;
   private Pref pref;

   private String[] items;

   public Person( int id ) {
      // Get info from database based off id
   }

   //accessor functions
}

public class Pref {
   private boolean isActive;

   etc.
}


Code:
Person pers = new pers( 1 );
   if ( pers.getName() == "admin" )
   ...

I figured that in CI, Person would be a model. However, I found out you cannot pass parameters to the constructor of models.

Some possible solutions:
- Add another function to set the id
- Create the Person as its own class, but I would lose access to the database functions
- Modify the Model class

Is there should be a better way of doing this in CI?

Thanks!
#2

[eluser]tonanbarbarian[/eluser]
I simply create a method in my model called load which you then call to get the record
Well actually I create a class that extends the core model and put the method in there so that all of my models can use the code

Code:
libraries/My_Model.php
class MY_Model extends CI_Model {

  var $_table = null;
  var $_key = 'id';

  functon MY_Model() {
    parent::CI_Model();
  } // MY_Model()

  function load($id) {
    if (empty($this->_table) OR empty($this->_key) OR empty($id))
      return false;
    $query = $this->db->getfrom($this->_table, $this->_key .'='. (int)$id);
    return $query->row(); // or return $query->row_array(); if you want the result as an array
  } // load()

}

Then the actual model would be
models/person.php
Code:
class Person extends MY_Model {
  var $_table = 'person';
  var $_id = 'id';

  // constructor
  function Person() {
    parent::MY_Model();
  } // Person()

}

then to instantiate in your controller you do
Code:
...
$this->load->model('person');
$data = $this->person->load(3);
...
#3

[eluser]Unknown[/eluser]
Code:
class MY_Model extends CI_Model {
...

Um, does this actually work?

Because as far as I can tell there is no CI_Model class. The base model class (at least in CI 1.5.4) is called 'Model' which led me to question whether you could actually extend it with a MY_ version like you can (most) of the the other core libraries.

My attempt to do it anyway didn't seem to work:

Code:
class MY_Model extends Model {
...

class Things extends MY_Model {
...

didn't work

The way the CI Loader library is written appears to also exclude overriding the CI model class with your own. Which is a shame and one wonders why? (why?!)

If it is possible to do this after all I'd love to hear some more details about how.

Otherwise I guess just have to extend the loader library first...
#4

[eluser]maadmac[/eluser]
[quote author="blueskiwi" date="1196547590"]
Um, does this actually work?[/quote]

In theory, sure. From the User Guide:

Quote:The Database classes can not be extended or replaced with your own classes, nor can the main Controller class. All other classes are able to be replaced/extended.
#5

[eluser]tonanbarbarian[/eluser]
I have had some instances where the base Model was not extended correctly, and I have had to autoload the Model and the extended Model class.
I think the issue is to do with paths because once I had my paths set correctly in my index.php I have not had a problem.
#6

[eluser]wiredesignz[/eluser]
I usually create a model based on the table with it's related database methods and then create a library which extends the model for each of the row objects.
#7

[eluser]CRHayes[/eluser]
There are many different opinions about what constitutes a "Model", a "Controller", and a "View". View is really simple...but there is a gray area with Model and Controller.

After asking the question multiple times myself, I finally decided the method I would stick with. You are creating an instance of the model (an object) everytime you load it. Therefore, you're model is an object. With that in mind, it should contain the functions relative to that object.

Ex: I am building a system that has a user membership system. One of my models is "User". It contains the functions for checking if a username or email address is already registered, inserting new member records, checking if entered Password/confirm password fields (during registration) equal each other, checking if user sessions exist, and getting profile information from the database.

Coinciding with what wiredesignz said, this model represents my 'member_profile' database table.

Whether this is how someone else does it or not, after much delibertion I think this is the way to do it. The functions contained in your model should relate to the object instance of that model.
#8

[eluser]tonanbarbarian[/eluser]
After looking more at the loader class code I can see what the issue is with extending the Model class.
The model method which is used to load a model is not designed in such a way to allow the Model class to be extended correctly

To fix this you can do 1 of 2 things
1. Hack the system/libraries/Loader.php
change line 159
Code:
require_once(BASEPATH.'libraries/Model'.EXT);
to
Code:
load_class('Model', false);

or create an extension to the loader to do it for you
application/libraries/MY_Loader.php
Code:
<?php
if (!defined('BASEPATH')) exit('No direct script access allowed');
class MY_Loader extends CI_Loader {

    /**
     * Constructor
     */
    function MY_Loader() {
        parent::CI_Loader();
    } // MY_Loader()

    /**
     * Model Loader
     *
     * This function lets users load and instantiate models.
     * Overridden so that the Model is loaded correctly and can be extended
     *
     * @access  public
     * @param   string  the name of the class
     * @param   mixed   any initialization parameters
     * @return  void
     */
    function model($model, $name = '', $db_conn = FALSE) {
        // load the Model class correctly so it can be extended
        if (!class_exists('Model')) {
            load_class('Model', false);
        }
        parent::model($model, $name, $db_conn);
    } // model()

} // class MY_Loader

I will be reporting this as a bug if it hasnt been already
#9

[eluser]dreamnid[/eluser]
Hi again,

Thanks for your replies.

The way I want to model the Person is you instantiate a person with a specific id. Then you can get attributes of the Person for that specific person.


For example:
Code:
$person = new Person( 32 );
echo $person->getId( );
echo $person->getEmail( );
echo $person->getWebsite( )->getTitle( );  // Get the website for the person and print out the title
Again, the last line is based off what I did in Java in one of my classes which I'm not sure how to translate it into CI.

From what I'm read so far, it seems that CodeIgnitor wants the id as a parameter to the member function, such as
Code:
$this->load->model('Person');
$this->model->getEmail( 32 );
$this->model->getWebsite( 32 )->getTitle()  // Not sure how this would work

To me, this requires each get function to make a different database call for each parameter that we're retrieving which adds overhead. Am I understanding this correctly?

For now, I've being creating the Person class as a library which seems to work okay, but I'm sure it is not ideal practice.

I'm trying to find other people's models to see what is supposed to be in a model and how they avoid querying the database for each parameter.

Thanks!
#10

[eluser]tonanbarbarian[/eluser]
Ok there is a minor issue in the CI way of doing things that you put up
after you load the model you reference it by the model name
Code:
$this->load->model('Person');
$this->person->getEmail(32);
...

Ok for what you want to do why not do something like this... just one extra line really
Code:
$this->load->model('Person');
$this->person->setId(32);
$this->person->getId( );
$this->person->getEmail( );
$this->person->getWebsite( )->getTitle( );

However if your getId method was to retrieve the data for the record with the specified id then my original way is basically the same




Theme © iAndrew 2016 - Forum software by © MyBB