Welcome Guest, Not a member yet? Register   Sign In
MySQL ActiveRecord - Protected identifier issue when updating?
#3

[eluser]gRoberts[/eluser]
Well spotted!

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

    class BaseModel extends Model
    {
        private $TableName;
        private $PrimaryKey;
        private $RemovedKey = 'Removed';
        private $Reserved = array('Key');

        private function escape($Input)
        {
            return '`' . $Input . '`';
        }

        public function __construct($TableName, $PrimaryKey, $RemovedKey = 'Removed')
        {
            parent::Model();

            $this->load->database();

            $this->TableName = $this->escape($TableName);
            $this->PrimaryKey = $PrimaryKey;
            $this->RemovedKey = $RemovedKey;
        }

        public function GetSingle($PrimaryID)
        {
            $this->db->where($this->PrimaryKey, $PrimaryID);
            $result = $this->db->get($this->TableName);
            $output = false;
            if($result->num_rows() > 0)
                $output = $result->row();
            $result->free_result();
            return $output;
        }

        public function GetActive()
        {
            $Key = $this->PrimaryKey;
            if($this->db->field_exists($this->RemovedKey, $this->TableName))
                $this->db->where(sprintf('(%1$s is null or %1$s = 0)', $this->RemovedKey));
            $result = $this->db->get($this->TableName);
            $output = array();
            if($result->num_rows() > 0)
            {
                foreach($result->result() as $row)
                    $output[$row->$Key] = $row;
            }
            $result->free_result();
            return $output;
        }

        public function Get()
        {
            $Key = $this->PrimaryKey;
            $result = $this->db->get($this->TableName);
            $output = array();
            if($result->num_rows() > 0)
            {
                foreach($result->result() as $row)
                    $output[$row->$Key] = $row;
            }
            $result->free_result();
            return $output;
        }

        public function Save($Row)
        {
            $Copy = clone $Row;
            $Fields = $this->db->field_data($this->TableName);
            foreach($Copy as $Key => $Value)
            {
                $found = false;
                foreach($Fields as $Field)
                {
                    if($Key == $Field->name)
                    {
                        $found = true;
                        break;
                    }
                }
                if(!$found) unset($Copy->$Key);
            }
            $X = new stdClass();
            foreach($Copy as $Key => $Value)
            {
                if(in_array($Key, $this->Reserved))
                    $NK = $this->escape($Key);
                else
                    $NK = $Key;
                $X->$NK = $Value;
            }
            $Copy = $X;
            unset($X);
            $PrimaryID = $this->PrimaryKey;
            if(isset($Row->$PrimaryID) && $Row->$PrimaryID !== null)
                $this->db->update($this->TableName, $Copy, array($this->PrimaryKey => $Copy->$PrimaryID));
            else
            {
                $this->db->insert($this->TableName, $Copy);
                $Row->$PrimaryID = $this->db->insert_id();
            }
            return $Row;
        }
    }
?>

Above is my BaseModel class. As you can see, you pass a table and primary key when creating it:

Code:
<?
    if (!defined('BASEPATH')) exit('No direct script access allowed');
    if(!class_exists('BaseModel')) require_once(APPPATH . 'libraries/Classes/BaseModel.class.php');

    class Address_model extends BaseModel
    {
        public function __construct() { parent::__construct('Address', 'AddressID'); }

        public function GetByUserID($UserID)
        {
            $this->db->where('UserID', $UserID);
            return $this->GetActive();
        }
    }
?>

This, like above allows me to expose Get, GetActive and GetSingle and if I need to create specific queries, I can simply create them in the actual model it self, and still reference the Get/GetActive/GetSingle afterwards.

In my above code, I have got around this issue by simply checking against my own list of reserved words and escaping those. I also have to TWO copies of the object being passed in, which is something i'm not happy about but it works.

I simply call Save on the model by passing it an object. If the object has been retrieved from the database, there will be a column as stated by the PrimaryKey.

If that PrimaryKey is present, it will update, otherwise it will insert.

Simples Wink

Cheers

Gavin


Messages In This Thread
MySQL ActiveRecord - Protected identifier issue when updating? - by El Forum - 08-05-2010, 08:54 AM



Theme © iAndrew 2016 - Forum software by © MyBB