Codeigniter — облегчаем себе жизнь (расширяем модель)

    В тех случаях когда нужен полноценный орм, рекомендую воспользоватся Doctrine, благо с Codeigniter'ом она очень хорошо интегрируется.

    Но бывает, что так много возможностей не нужно, а прописывать CRUD к каждой таблице долго и утомительно.

    Очевидное решение рассширить модель.
    Итак создаём файл MY_model.php(/system/application/libraries/MY_model.php)

    <? php
    class MY_model extends model{
       private $key_field    = null;
       private $table    = null;
       private $params    = array();
       private $item        = array();
       
       public function MY_model($table = null){
          parent::model();
          if($table != null){
             $this->setFields($table);
          }
       }
       
       public function setFields($table, $key_field){
             $fields = $this->db->list_fields($table);
             foreach ($fields as $field)
             {
                $table_fields[] = $field;
             }
             $this->params = $table_fields;
             $this->table = $table;
             $this->key_field = $key_field;
       }
       
       public function getItem(array $searchValues){
          foreach($searchValues as $key => $value){
             if(!in_array($key,$this->params)){
                show_error('wrong searchValues');
                die();
             }
          }

          $query = $this->db->get_where($this->table, $searchValues, 1);
             if($query->num_rows() < 1){
                show_error('can\'t find entry ');
                die();
             }
             else if($query->num_rows() > 1){
                show_error('found multiply entries');
                die();            
             }
             else{
                foreach($query->result_array() as $row){
                   $this->item = $row;
                }
             }
       }
       
       public function editItem(array $editValues){
          if($this->item === array()){
             show_error('no item to edit');
             die();
          }
          else{
             foreach($editValues as $key => $value){
                if(!in_array($key,$this->params)){
                   show_error('wrong editValues');
                   die();
                }
             }
             
             foreach($editValues as $key => $value){
                $this->item[$key] = $value;
             }
          }

       }
       
       public function saveItem(){
          if($this->item === array()){
             show_error('no item to save');
             die();
          }

          if($this->key_field == null){
             show_error('no key_field defined');
             die();
          }
          
          if(array_key_exists($this->key_field,$this->item) && $this->item != array()){

             $this->db->where($this->key_field, $this->item[$this->key_field]);
             $this->db->update($this->table, $this->item);
          }
          else{
             $this->db->insert($this->table, $this->item);
          }
       }
       
       public function deleteItem(){
          if($this->item === array()){
             show_error('no item to delete');
             die();
          }
          
          if($this->key_field == null){
             show_error('no key_field defined');
             die();
          }

          if(array_key_exists($this->key_field,$this->item) && $this->key_field != null){
             $this->db->delete($this->table, array( $this->key_field => $this->item[$this->key_field]));      
          }
          else{
             show_error('no id set to delete an entry');
             die();
          }
       }
       
       public function newItem(array $newValues){

             foreach($newValues as $key => $value){
                if(!in_array($key,$this->params)){
                   show_error('wrong newValues');
                   die();
                }
             }
             $this->item = $newValues;

       }
       
       public function cleanItem(){
          $this->item = array();
       }
    }
    * This source code was highlighted with Source Code Highlighter.


    В файле autoload.php (/system/application/config/autoload.php)
    пишем загружаем необходимые классы
    <сode>
    $autoload['libraries'] = array('database','model','MY_model');


    Приготовления законченны.
    теперь надо бы это дело как-то использовать.

    допустим у нас мы создаём таблицу где мы собираемся хранить адреса e-mail со следующей структурой:
    CREATE TABLE `email_list` (
     `id` int(11) NOT NULL auto_increment,
     `email` varchar(255) NOT NULL,
     PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
    * This source code was highlighted with Source Code Highlighter.


    создаём модель:
    <? php
    class Email_model extends MY_Model
    {
      function Email_model(){
       parent::MY_Model();
      }
    }
    * This source code was highlighted with Source Code Highlighter.

    Всё больше ничего писать не надо, можно сразу начать пользовать

    Вот как применение будет выглядет создание новой записи в контроллере:
    <? php
    class Email extends Controller {

    function Email(){
      parent::Controller;
      // Загружаем модель для доступа во всех методах контроллера
      $this->load->model('Email_model');
      // имя таблицы и ключ
      $this->Email_model->setFields('email_list','id');
    }

    function index()
    {
      // создаём новую запись
      $this->Email_model->newItem(array('email' => 'someemail@somedomain.com'));
      // сохраняем запись
      $this->Email_model->saveItem();
      // очищаем запись
      $this->Email_model->cleanItem();
      // находим запись по полю по значению поля email
      $this->Email_model->getItem(array('email' => 'someemail@somedomain.com'));
      // редактируем её
      $this->Email_model->editItem(array('email' => 'someotheremail@somedomain.com'));
      // сохраняем запись
      $this->Email_model->saveItem();
      // стираем запись
      $this->Email_model->deleteItem();
      // очищаем запись
      $this->Email_model->cleanItem();
    }
    * This source code was highlighted with Source Code Highlighter.


    Вот собственно и всё. Решение не претендует на универсальность, однако в некоторых случаях может облегчить жизнь
    Поделиться публикацией

    Комментарии 11

      +1
      Привет, а чем это отличается от ActiveRecord?
        0
        Пока не понял всего смысла этой конструкции, чем это

        $this->Email_model->newItem(array('email' => '<a href="mailto:someemail@somedomain.com">someemail@somedomain.com</a>'));
        $this->Email_model->saveItem();

        удобнее чем

        $this->db->insert('table_name', array('email' => '<a href="mailto:someemail@somedomain.com">someemail@somedomain.com</a>'));
          0
          Разница в том, что благодаря Doctrine удобнее работать с отношениями один к одному, многие ко многим и т.д. Почитайте что такое ORM: http://ru.wikipedia.org/wiki/ORM
            0
            Это понятно, но здесь автор предлагает не пользоваться Doctrine, а расширить модель его способом. Но я пока не увидел в этом способе необходимости.
              0
              Да, что-то я невнимательно пост посмотрел...
                0
                я как раз за ОРМ, просто иногда это ох как расточительно.
              0
              Если рассматривать способ вставки в отдельности, то разницы практически нету, за исключением того, что вы все равно бы писали метод в модели и вызывали его а не $this->db->insert() из контроллера.

              Далее, если почитать внимательно цель этой билиотеки, не заменить орм, а облегчить написание СRUD и освободить пользователя от написания рутинных методов в модели.
              0
              А почему Вы в конструкторе контроллера пишете инициализацию «ORM»
                0
                Вы что имете ввиду? load->model и setFields? Если да, то на мой взгляд достаточно подходящие место, так как скорее всего модель будет использованна во всех методах конторллера, соответственно не нужно будет инициализировать в каждом методе.
                +1
                я имею введу $this->Email_model->setFields('email_list','id');

                а почему не разместить инициализацию в конструкторе Вашей модели Email_model. Тогда даже в контроллерах не нада писать инициализацию… т.к. Email_model может использоваться в нескольких контроллерах.
                  0
                  а кстати да )) туплю )))

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое