Advertisement
bkader

MY_Model using Idiorm class

Apr 6th, 2017
587
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 18.28 KB | None | 0 0
  1. <?php
  2. defined('BASEPATH') OR exit('No direct script access allowed');
  3.  
  4. /**
  5.  * MY_Model
  6.  *
  7.  * This base model attempts to use idiorm class instead of CodeIgniter
  8.  * query builder.
  9.  *
  10.  * @see     https://github.com/j4mie/idiorm (original)
  11.  * @see     https://github.com/bkader/idiorm (used for this)
  12.  *
  13.  * @package     CodeIgniter
  14.  * @category    Core Extension
  15.  * @author  Kader Bouyakoub <bkader@mail.com>
  16.  * @link    https://github.com/bkader
  17.  * @link    https://twitter.com/KaderBouyakoub
  18.  */
  19. class_exists('ORM', false) OR require APPPATH.'third_party/idiorm/idiorm.php';
  20. class MY_Model extends CI_Model
  21. {
  22.     /**
  23.      * holds the current model class name.
  24.      * @var string
  25.      */
  26.     protected $_model = null;
  27.  
  28.     /**
  29.      * holds the current table depending on the model class name.
  30.      * @var string
  31.      */
  32.     protected $_table = null;
  33.  
  34.     /**
  35.      * holds ORM class instance.
  36.      * @var object
  37.      */
  38.     protected $_database = null;
  39.  
  40.     /**
  41.      * table's primary key.
  42.      * @var string
  43.      */
  44.     protected $_primary_key = 'id';
  45.  
  46.     /**
  47.      * whether to turn ON soft deletes or not.
  48.      * @var boolean
  49.      */
  50.     protected $_soft_delete = false;
  51.  
  52.     /**
  53.      * data return type: array o object.
  54.      * @var string
  55.      */
  56.     protected $_return_type = 'object';
  57.  
  58.     /**
  59.      * if TRUE, use unix_timestamp.
  60.      * @var boolean
  61.      */
  62.     protected $unix_timestamp = true;
  63.  
  64.     /**
  65.      * MySQL datetime format.
  66.      * @var string
  67.      */
  68.     protected $datetime_format = 'Y-m-d H:i:s';
  69.  
  70.     /**
  71.      * column that holds date of creation.
  72.      * @var string
  73.      */
  74.     protected $_created_at = 'created_at';
  75.    
  76.     /**
  77.      * column that holds date of update.
  78.      * @var string
  79.      */
  80.     protected $_updated_at = 'updated_at';
  81.  
  82.     /**
  83.      * column that holds date of delete.
  84.      * @var string
  85.      */
  86.     protected $_deleted_at = 'deleted_at';
  87.  
  88.     /**
  89.      * if set to TRUE, data will not be passed to form validation.
  90.      * @var boolean
  91.      */
  92.     protected $_skip_validation = false;
  93.  
  94.     /**
  95.      * array of form validation rules.
  96.      * @see https://codeigniter.com/user_guide/libraries/form_validation.html?highlight=form%20validation#setting-validation-rules
  97.      * @var array
  98.      */
  99.     protected $_validation_rules = array();
  100.  
  101.     /**
  102.      * Attributes that will be ignored and removed from insert or update.
  103.      * @var array
  104.      */
  105.     protected $protected_attributes = array();
  106.  
  107.     /**
  108.      * Observers.
  109.      */
  110.     protected $before_create = array();
  111.     protected $after_create  = array();
  112.     protected $before_find   = array();
  113.     protected $after_find    = array();
  114.     protected $before_update = array();
  115.     protected $after_update  = array();
  116.     protected $before_delete = array();
  117.     protected $after_delete  = array();
  118.  
  119.     public function __construct()
  120.     {
  121.         parent::__construct();
  122.         $this->_set_model();
  123.         $this->_set_table();
  124.         $this->_set_database();
  125.  
  126.         array_unshift($this->before_create, 'protect_attributes', 'created_at');
  127.         array_unshift($this->before_update, 'protect_attributes', 'updated_at');
  128.     }
  129.  
  130.     // ------------------------------------------------------------------------
  131.  
  132.     public function __call($method, $params)
  133.     {
  134.         // No table set? Nothing to do.
  135.         if (empty($this->_table))
  136.         {
  137.             show_error("Table name is not set for '{$this->_model}' class.");
  138.         }
  139.  
  140.         // Add methods to observers.
  141.         if (preg_match('/^before_([^)]+)$/', $method, $m))
  142.         {
  143.             if (isset($this->{$m[0]}) && is_array($this->{$m[0]}))
  144.             {
  145.                 is_array($params[0]) && $params = $params[0];
  146.  
  147.                 foreach ($params as $param)
  148.                 {
  149.                     array_push($this->{$m[0]}, $param);
  150.                 }
  151.             }
  152.  
  153.             return $this;
  154.         }
  155.  
  156.         // The method exists in this class? Call it.
  157.         if (method_exists($this, $method))
  158.         {
  159.             return call_user_func_array(array($this, $method), $params);
  160.         }
  161.  
  162.         // Retrieve by a given column name?
  163.         if (preg_match('/^get_by_([^)]+)$/', $method, $m) && count($m) == 2)
  164.         {
  165.             $field = $m[1];
  166.             $match = array_shift($params);
  167.  
  168.             if (strpos($field, '_or_'))
  169.             {
  170.                 $field = explode('_or_', $field);
  171.             }
  172.  
  173.             $result = false;
  174.  
  175.             if (is_array($field))
  176.             {
  177.                 foreach ($field as $_field)
  178.                 {
  179.                     if ($found = $this->get_by($_field, $match, $params))
  180.                     {
  181.                         $result = $found;
  182.                         break;
  183.                     }
  184.                 }
  185.             }
  186.             else
  187.             {
  188.                 $result = $this->get_by($field, $match, $params);
  189.             }
  190.  
  191.             return $result;
  192.         }
  193.  
  194.         // Update a row using update_by() method
  195.         if (preg_match('/^update_by_([^)]+)$/', $method, $m) && count($m) == 2)
  196.         {
  197.             array_unshift($params, $m[1]);
  198.             return call_user_func_array(array($this, 'update_by'), $params);
  199.         }
  200.  
  201.         // Delete a row using delete_by() method
  202.         if (preg_match('/^delete_by_([^)]+)$/', $method, $m) && count($m) == 2)
  203.         {
  204.             array_unshift($params, $m[1]);
  205.             return call_user_func_array(array($this, 'delete_by'), $params);
  206.         }
  207.  
  208.         // Remove records even if $soft_delete is set to true.
  209.         if (strpos($method, 'remove') === 0)
  210.         {
  211.             $method = str_replace('remove', 'delete', $method);
  212.             $this->_soft_delete = false;
  213.             return call_user_func_array(array($this, $method), $params);
  214.         }
  215.  
  216.         // The method exists in ORM object? Call it.
  217.         if (method_exists(ORM::for_table($this->_table), $method))
  218.         {
  219.             return call_user_func_array(
  220.                 array(ORM::for_table($this->_table), $method),
  221.                 $params
  222.             );
  223.         }
  224.  
  225.         // No method found? Show error.
  226.         show_error("Undefined method '{$this->_model}::{$method}()'.");
  227.     }
  228.  
  229.     // ------------------------------------------------------------------------
  230.     // FINDERS
  231.     // ------------------------------------------------------------------------
  232.  
  233.     /**
  234.      * Retrieves a single record by its primary value with optional select.
  235.      */
  236.     public function get()
  237.     {
  238.         $args = func_get_args();
  239.         $primary_value = array_shift($args);
  240.  
  241.         if ( ! empty($args))
  242.         {
  243.             is_array($args[0]) && $args = $args[0];
  244.  
  245.             foreach ($args as $arg)
  246.             {
  247.                 $query = $this->_database->select($arg);
  248.             }
  249.         }
  250.  
  251.         $result = $this->_database->find_one($primary_value);
  252.  
  253.         return $result ? $result->{'as_'.$this->_return_type}() : false;
  254.     }
  255.  
  256.     /**
  257.      * Retrieves a single record by $field=$match condition with option select.
  258.      */
  259.     public function get_by()
  260.     {
  261.         $args = func_get_args();
  262.  
  263.         if (empty($args))
  264.         {
  265.             return false;
  266.         }
  267.  
  268.         $field = array_shift($args);
  269.         $match = is_array($field) ? null : array_shift($args);
  270.  
  271.         // $query = ORM::for_table($this->_table);
  272.  
  273.         if ( ! empty($args))
  274.         {
  275.             is_array($args[0]) && $args = $args[0];
  276.             foreach ($args as $arg)
  277.             {
  278.                 $query = $this->_database->select($arg);
  279.             }
  280.         }
  281.  
  282.         $result = $this->_database->where($field, $match)->find_one();
  283.         return $result ? $result->{'as_'.$this->_return_type}() : false;
  284.     }
  285.  
  286.     /**
  287.      * Retrieves multiple records by conditions with optional select.
  288.      */
  289.     public function get_many()
  290.     {
  291.         $args = func_get_args();
  292.  
  293.         if (empty($args))
  294.         {
  295.             return false;
  296.         }
  297.  
  298.         $field = array_shift($args);
  299.         $match = is_array($field) ? null : array_shift($args);
  300.  
  301.         $query = ORM::for_table($this->_table);
  302.  
  303.         if ( ! empty($args))
  304.         {
  305.             is_array($args[0]) && $args = $args[0];
  306.             foreach ($args as $arg)
  307.             {
  308.                 $query = $query->select($arg);
  309.             }
  310.         }
  311.  
  312.         if ($result = $query->find_many())
  313.         {
  314.             foreach ($result as &$row)
  315.             {
  316.                 $row = $row->{'as_'.$this->_return_type}();
  317.             }
  318.  
  319.             return $result;
  320.         }
  321.  
  322.         return false;
  323.     }
  324.  
  325.     // ------------------------------------------------------------------------
  326.     // INSERT
  327.     // ------------------------------------------------------------------------
  328.  
  329.     /**
  330.      * Insert a new row into the table. $data should be an associative array
  331.      * of data to be inserted. Returns newly created ID.
  332.      */
  333.     public function insert(array $data = array(), $validate = true)
  334.     {
  335.         if ($validate === true)
  336.         {
  337.             $data = $this->validate($data);
  338.         }
  339.  
  340.         if ($data !== false)
  341.         {
  342.             $data = $this->trigger('before_create', $data);
  343.  
  344.             $row = $this->_database->create($data);
  345.  
  346.             if ($row->save())
  347.             {
  348.                 $id = $row->id();
  349.  
  350.                 $this->trigger('after_create', $id);
  351.  
  352.                 return $id;
  353.             }
  354.  
  355.             return false;
  356.         }
  357.  
  358.         return false;
  359.     }
  360.  
  361.     /**
  362.      * Insert multiple rows into the table. Returns an array of multiple IDs.
  363.      */
  364.     public function insert_many(array $data = array(), $validate = true)
  365.     {
  366.         if (empty($data))
  367.         {
  368.             return false;
  369.         }
  370.  
  371.         $ids = array();
  372.  
  373.         foreach ($data as $key => $row)
  374.         {
  375.             $ids[] = $this->insert($row, $validate, ($key = count($data) - 1));
  376.         }
  377.  
  378.         return $ids;
  379.     }
  380.  
  381.     // ------------------------------------------------------------------------
  382.     // UPDATERS
  383.     // ------------------------------------------------------------------------
  384.  
  385.     /**
  386.      * Updated a single record based on the primary value.
  387.      */
  388.     public function update($primary_value, $data, $validate = true)
  389.     {
  390.         if ($validate === true)
  391.         {
  392.             $data = $this->validate($data);
  393.         }
  394.  
  395.         if ($data !== false)
  396.         {
  397.             // We check the row exists before proceeding.
  398.             $row = $this->_database->find_one($primary_value);
  399.  
  400.             if ($row)
  401.             {
  402.                 $data = $this->trigger('before_update', $data);
  403.                
  404.                 $row->set($data);
  405.                 $result = $row->save();
  406.  
  407.                 $this->trigger('after_update', array($data, $result));
  408.  
  409.                 return $result;
  410.             }
  411.  
  412.             return false;
  413.         }
  414.  
  415.         return false;
  416.     }
  417.  
  418.     /**
  419.      * Updated a single record based on WHERE conditions.
  420.      */
  421.     public function update_by()
  422.     {
  423.         $args = func_get_args();
  424.  
  425.         if (empty($args))
  426.         {
  427.             return false;
  428.         }
  429.  
  430.         $data = array_pop($args);
  431.         if ( ! is_array($data) OR empty($data) OR empty($args))
  432.         {
  433.             return false;
  434.         }
  435.  
  436.         $data = $this->trigger('before_update', $data);
  437.  
  438.         if ($this->validate($data) !== false)
  439.         {
  440.             $field = array_shift($args);
  441.             $match = is_array($field) ? null : array_shift($args);
  442.  
  443.             $update = ORM::for_table($this->_table)
  444.                         ->where($field, $match)
  445.                         ->find_one();
  446.  
  447.             if ( ! $update)
  448.             {
  449.                 return false;
  450.             }
  451.  
  452.             $update->set($data);
  453.             $result = $update->save();
  454.             $this->trigger('after_update', array($data, $result));
  455.             return $result;
  456.         }
  457.  
  458.         return false;
  459.     }
  460.  
  461.     /**
  462.      * Update many records, based on WHERE clause.
  463.      */
  464.     public function update_many()
  465.     {
  466.         $args = func_get_args();
  467.         if (empty($args))
  468.         {
  469.             return false;
  470.         }
  471.  
  472.         $data = array_pop($args);
  473.         if ( ! is_array($data) OR empty($data) OR empty($args))
  474.         {
  475.             return false;
  476.         }
  477.  
  478.         $data = $this->trigger('before_update', $data);
  479.  
  480.         if ($this->validate($data) !== false)
  481.         {
  482.             $field = array_shift($args);
  483.             $match = is_array($field) ? null : array_shift($args);
  484.  
  485.             $update = ORM::for_table($this->_table)
  486.                         ->where($field, $match)
  487.                         ->find_many();
  488.  
  489.             if ( ! $update)
  490.             {
  491.                 return false;
  492.             }
  493.  
  494.             $result = true;
  495.             foreach ($update as $row)
  496.             {
  497.                 $row->set($data);
  498.                 $result = $row->save();
  499.             }
  500.  
  501.             $this->trigger('after_update', array($data, $result));
  502.             return $result;
  503.         }
  504.  
  505.         return false;
  506.     }
  507.  
  508.     // ------------------------------------------------------------------------
  509.     // DELETERS
  510.     // ------------------------------------------------------------------------
  511.  
  512.     /**
  513.      * Delete a row from the table by the primary value
  514.      */
  515.     public function delete($primary_value)
  516.     {
  517.         $row = $this->_database->find_one($primary_value);
  518.  
  519.         if ( ! $row)
  520.         {
  521.             return false;
  522.         }
  523.  
  524.         if ($this->_soft_delete === true)
  525.         {
  526.             // Update the row only if its not deleted.
  527.             if ($row->{$this->_deleted_at} < 1)
  528.             {
  529.                 $row->set($this->_deleted_at, $this->_get_timestamp());
  530.                 return $row->save();
  531.             }
  532.  
  533.             return true;
  534.         }
  535.  
  536.         return $row->delete();
  537.     }
  538.  
  539.     /**
  540.      * Delete a row from the database table by an arbitrary WHERE clause
  541.      */
  542.     public function delete_by()
  543.     {
  544.         $args = func_get_args();
  545.         if (empty($args))
  546.         {
  547.             return false;
  548.         }
  549.  
  550.         $field = array_shift($args);
  551.         $match = is_array($field) ? null : array_shift($args);
  552.  
  553.         $row = $this->_database->where($field, $match)->find_one();
  554.  
  555.         if ( ! $row)
  556.         {
  557.             return false;
  558.         }
  559.  
  560.         if ($this->_soft_delete === true)
  561.         {
  562.             // Update the row only if its not deleted.
  563.             if ($row->{$this->_deleted_at} < 1)
  564.             {
  565.                 $row->set($this->_deleted_at, $this->_get_timestamp());
  566.                 return $row->save();
  567.             }
  568.  
  569.             return true;
  570.         }
  571.  
  572.         return $row->delete();
  573.     }
  574.  
  575.     /**
  576.      * Delete many rows from the database table by multiple primary values
  577.      */
  578.     public function delete_many()
  579.     {
  580.         $args = func_get_args();
  581.         if (empty($args))
  582.         {
  583.             return false;
  584.         }
  585.  
  586.         $field = array_shift($args);
  587.         $match = is_array($field) ? null : array_shift($args);
  588.  
  589.         $rows = $this->_database->where($field, $match)->find_many();
  590.         if ( ! $rows)
  591.         {
  592.             return false;
  593.         }
  594.  
  595.         if ($this->_soft_delete === true)
  596.         {
  597.             // To avoid time being updated, we store it.
  598.             $deleted_at = $this->_get_timestamp();
  599.             foreach ($rows as $row)
  600.             {
  601.                 // Update the row only if it's not already deleted.
  602.                 if ($row->{$this->_deleted_at} < 1)
  603.                 {
  604.                     $row->set($this->_deleted_at, $deleted_at);
  605.                     $row->save();
  606.                 }
  607.             }
  608.         }
  609.         else
  610.         {
  611.             foreach ($rows as $row)
  612.             {
  613.                 $row->delete();
  614.             }
  615.         }
  616.  
  617.         return true;
  618.     }
  619.  
  620.     // ------------------------------------------------------------------------
  621.     // INTERNAL METHODS
  622.     // ------------------------------------------------------------------------
  623.  
  624.     /**
  625.      * Triggers and event and call its observer.
  626.      */
  627.     public function trigger($event, $data = array())
  628.     {
  629.         if (isset($this->{$event}) && is_array($this->{$event}))
  630.         {
  631.             foreach ($this->$event as $method)
  632.             {
  633.                 $data = $this->{$method}($data);
  634.             }
  635.         }
  636.  
  637.         return $data;
  638.     }
  639.  
  640.     /**
  641.      * Run form validation on the passed data.
  642.      *
  643.      * @param   array   $data
  644.      * @return  mixed   array after validation or false.
  645.      */
  646.     public function validate($data = array())
  647.     {
  648.         if ($this->_skip_validation)
  649.         {
  650.             return $data;
  651.         }
  652.  
  653.         if ( ! empty($this->_validation_rules))
  654.         {
  655.             foreach ($data as $key => $val)
  656.             {
  657.                 $_POST[$key] = $val;
  658.             }
  659.  
  660.             if ( ! class_exists('CI_Form_validation', false))
  661.             {
  662.                 $this->load->library('form_validation');
  663.             }
  664.  
  665.             if (is_array($this->_validation_rules))
  666.             {
  667.                 $this->form_validation->set_rules($this->_validation_rules);
  668.  
  669.                 if ($this->form_validation->run() == true)
  670.                 {
  671.                     return $data;
  672.                 }
  673.                 else
  674.                 {
  675.                     return false;
  676.                 }
  677.             }
  678.             else
  679.             {
  680.                 if ($this->form_validation->run($this->_validation_rules) == true)
  681.                 {
  682.                     return $data;
  683.                 }
  684.                 else
  685.                 {
  686.                     return false;
  687.                 }
  688.             }
  689.         }
  690.  
  691.         return $data;
  692.     }
  693.  
  694.     /**
  695.      * Fetches the current model class name.
  696.      */
  697.     private function _set_model()
  698.     {
  699.         if (empty($this->_model))
  700.         {
  701.             $this->_model = ucfirst(get_class($this));
  702.         }
  703.     }
  704.  
  705.     /**
  706.      * Guesses the current table name from model class name.
  707.      */
  708.     private function _set_table()
  709.     {
  710.         if ($this->_table == null)
  711.         {
  712.             function_exists('plural') OR $this->load->helper('inflector');
  713.             $this->_table = plural(preg_replace('/(_m|_model)?$/', '', strtolower($this->_model)));
  714.         }
  715.     }
  716.  
  717.     /**
  718.      * Estalishes the connection to the database.
  719.      */
  720.     private function _set_database()
  721.     {
  722.         if (file_exists($db_config = APPPATH.'config/'.ENVIRONMENT.'/database.php'))
  723.         {
  724.             include($db_config);
  725.         }
  726.         elseif (file_exists($db_config = APPPATH.'config/database.php'))
  727.         {
  728.             include($db_config);
  729.         }
  730.  
  731.         $db_group = isset($active_group) ? $active_group : 'default';
  732.         $config = $db[$db_group];
  733.         $params = array(
  734.             'dsn'    => isset($config['dsn']) ? rawurldecode($config['dsn']) : '',
  735.             'host'   => isset($config['hostname']) ? $config['hostname'] : 'localhost',
  736.             'port'   => isset($config['port']) ? $config['port'] : '3306',
  737.             'user'   => isset($config['username']) ? $config['username'] : '',
  738.             'pass'   => isset($config['password']) ? $config['password'] : '',
  739.             'dbname' => isset($config['database']) ? $config['database'] : '',
  740.             'pref'   => isset($config['dbprefix']) ? $config['dbprefix'] : '',
  741.             'driver' => isset($config['dbdriver']) ? $config['dbdriver'] : 'mysqli',
  742.         );
  743.  
  744.         $params['driver'] = ($params['driver'] == 'sqltie') ? 'sqltie' : 'mysql';
  745.  
  746.         // echo '<pre>', print_r($params, true);
  747.         // exit;
  748.  
  749.         if (empty($params['dsn']))
  750.         {
  751.             if (empty($params['host'])
  752.                 OR empty($params['user'])
  753.                 OR empty($params['dbname']))
  754.             {
  755.                 show_error('No database connection settings were found in the database config file.');
  756.             }
  757.             else
  758.             {
  759.                 if ($params['driver'] == 'mysql')
  760.                 {
  761.                     $params['dsn'] = "{$params['driver']}:host={$params['host']};";
  762.                     if ( ! empty($params['post']))
  763.                     {
  764.                         $params['dsn'] .= "port={$param['port']};";
  765.                     }
  766.                     $params['dsn'] .= "dbname={$params['dbname']};";
  767.                 }
  768.             }
  769.         }
  770.  
  771.         ORM::configure($params['dsn'], null, $db_group);
  772.         ORM::configure('username', $params['user']);
  773.         ORM::configure('password', $params['pass']);
  774.  
  775.         $this->_database = ORM::for_table($this->_table);
  776.     }
  777.  
  778.     // ------------------------------------------------------------------------
  779.     // OBSERVERS
  780.     // ------------------------------------------------------------------------
  781.  
  782.     /**
  783.      * Protects attributes by removing them from $data.
  784.      */
  785.     protected function protect_attributes($data)
  786.     {
  787.         foreach ($this->protected_attributes as $attr)
  788.         {
  789.             if (is_object($data))
  790.             {
  791.                 unset($data->{$attr});
  792.             }
  793.             else
  794.             {
  795.                 unset($data[$attr]);
  796.             }
  797.         }
  798.  
  799.         return $data;
  800.     }
  801.  
  802.     /**
  803.      * Add date of creation to $data before insert.
  804.      */
  805.     protected function created_at($data)
  806.     {
  807.         if (is_object($data) && empty($data->{$this->_created_at}))
  808.         {
  809.             $data->{$this->_created_at} = $this->_get_timestamp();
  810.         }
  811.         elseif (is_array($data) && empty($data[$this->_created_at]))
  812.         {
  813.             $data[$this->_created_at] = $this->_get_timestamp();
  814.         }
  815.  
  816.         return $data;
  817.     }
  818.  
  819.     /**
  820.      * Add date of update to $data before update.
  821.      */
  822.     protected function updated_at($data)
  823.     {
  824.         if (is_object($data) && empty($data->{$this->_updated_at}))
  825.         {
  826.             $data->{$this->_updated_at} = $this->_get_timestamp();
  827.         }
  828.         elseif (is_array($data) && empty($data[$this->_updated_at]))
  829.         {
  830.             $data[$this->_updated_at] = $this->_get_timestamp();
  831.         }
  832.  
  833.         return $data;
  834.     }
  835.  
  836.     /**
  837.      * Set time() depending on the property $this->unix_timestamp
  838.      */
  839.     public function _get_timestamp()
  840.     {
  841.         if ($this->unix_timestamp === true)
  842.         {
  843.             return time();
  844.         }
  845.  
  846.         return date($this->datetime_format);
  847.     }
  848. }
  849.  
  850. /* End of file MY_Model.php */
  851. /* Location: ./application/core/MY_Model.php */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement