Question

im using Codeigniter 3.0 query builder, my question when ever my model return a user i'm returning a database row. not an object -its stdobject but not try object- is this anything related to oop practice ?

my auth model is simple

class user extend CI_MODEL{

funciton attempt($user,$pass){

//do validation and fetch user and compare pass etc...

$query = $this->db->get_where('users',$where);

return $query->result() //now this is my line of question

}

}

so i think this is nothing related to oop ? -or am i wrong ? - its just procedural code using classes for organization !.

so what is the correct way in oop manner ?

I have goan through many auth libraries for codeigntier to see how they do it, and all what i see is they save user row to an array variable in model. yet all users are still inside only 1 user object .

should i create an abstract class/interfaces for user object and pass database row to it every time i fetch a user before i save them to my Big ci_model ?

if so is this doable in codeigniter ? where would i put this abstract classes ?

Was it helpful?

Solution

I have done somthing like this, and yes I have created a model_row class to pass all data to in a array_walk style:

if ($qry = $this->db->get()) {
  $res = $qry->result();

  return $this->_instantiateRows($res);
}

Function _instantiateRows():

/**
   * Get the row class name
   * Checks if a class exists with the model name _Row
   * @return string
   */
  private function _getRowClass() {
    $modelName = get_class($this);
    return class_exists($modelName.'_Row') ? $modelName.'_Row' : 'Model_Row';
  }

  /**
   * Formats results into model row classes
   * @param array $results
   * @return array
   */
  protected function _instantiateRows($results) {
    $rowClass = $this->_getRowClass();
    $self = $this;

    array_walk($results,function(&$row,$k) use ($rowClass, $self) {
      $row = new $rowClass($row,$self,$k);
    });

    return $results;
  }

Then a row class:

/**
 * Model row class
 * Acts as a baseclass and a fallback class for database rows
 * Implements standard methods, for saving, getting the ID, and setting field
 * values.
 * @property $_model MY_Model
 * @property $_key Original Array key
 * @property $_ID_FIELD name of the id field
 */
class Model_Row
{
  protected $_isNew = True;
  protected $_model = False;
  protected $_key = False;
  protected $_ID_FIELD = 'id';
  protected $_ID_ORIGINAL = False;

  /**
   * C'tor
   * Sets up the object with data from the row
   * @param object $data
   * @param object $model
   * @param int $key
   * @param string $id_field
   */
  public function __construct($data,$model,$key=False) {
    $this->_key = $key;

    // If no key is specified then it must be new / Not from database
    if ($this->_key !== False)
      $this->_isNew = False;

    $data = (array)$data;
    $this->_model = $model;
    $this->_ID_FIELD = $model->idField;

    $this->set($data);

    // Ensure ID Field is set.
    $idF = $this->_ID_FIELD;
    if (!isset($this->$idF))
      $this->$idF = null;
  }

  /**
   * Get the ID field
   * ID Field could be named differently for each model, this is an easy
   * shortcut to it.
   * @param string $setTo - set the id to this value
   * @return string
   */
  public function id($setTo=False) {
    $idF = $this->_ID_FIELD;

    if ($setTo !== False) {
      if ($this->_ID_ORIGINAL === False && !$this->_isNew)
        $this->_ID_ORIGINAL = $this->$idF;

      $this->set($idF,$setTo);
    }

    return $this->$idF !== null ? (string)$this->$idF : False;
  }

  /**
   * Save this row
   * @return bool
   */
  public function save() {
    $wheres = array();

    if (!$this->_isNew) {
      $idF = $this->_ID_FIELD;
      $wheres[$idF] = $this->_ID_ORIGINAL ?: $this->id();
    }

    $res = $this->_model->set($this,$wheres);

    if ($this->id() === False)
      $this->id($this->_model->insertID());

    // Reset the original id field
    $this->_ID_ORIGINAL = False;
    $this->_isNew = False;

    if ($res)
      return $this;

    return False;
  }

  /**
   * Set object properties
   * can be passed by array field => value
   * @param mixed $field
   * @param mixed $value
   * @return null
   */
  public function set($field,$value=False) {
    if ((is_array($field) || is_object($field)) && $value === False) {
      if (is_object($field))
        $field = (array)$field;

      foreach($field as $f => $v)
        $this->set($f,$v);
    }
    else {
      if (method_exists($this, 'set_'.$field))
        call_user_func(array($this,'set_'.$field), $value);
      else
        $this->$field = $value;
    }
  }
}

The point of the _getRowClass is to check for a class called model_name_row if this exists, then instantiate the data to this class, otherwise fall back to the baseclass model_row

There are some other things your model will need too, because the row class will be passed the model, so your model will need a public $idField='id' , and then this function can be usefull on your model:

/**
   * Create a new record using the model row class
   * @param mixed $data
   * @return Model_Row
   */
  public function newRow($data=array()) {
    $rowClass = $this->_getRowClass();
    return new $rowClass($data,$this);
  }

So you can do $newRow = $this->Model->newRow($data) which will create a new row, then can call $newRow->save() and other methods if set...

* EDIT

Also to point out, I use $this->_model->set($this, $wheres) on the row class, this is because I have defined a baseclass with a public setter:

/**
   * Setter
   * @param mixed $data object or array
   * @param mixed $wheres object or array query
   * @return bool
   */
  public function set($data,$wheres=array()) {
    if (!$this->checkTableSet())
      return False;

    if (empty($wheres)) {
      return $this->db->insert($this->table,$data);
    }
    else {
      $this->db->where($wheres);
      return $this->db->update($this->table,$data);
    }
  }

$this->table is a model variable with the table name, e.g. protected $table='users'; and the function checkTableSet() simply checks whether this has been set and not empty..

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top