Абстрактная базовая модель Codeigniter

Можно ли реализовать абстрактную базовую модель в Codeigniter? Я создал абстрактный класс с базовыми функциями CRUD, но получаю сообщение об ошибке «Невозможно создать экземпляр абстрактного класса».

Абстрактная модель находится в /application/core/my_model.php и просто

abstract class MY_Model extends CI_Model
{

Невозможно создать экземпляр абстрактного класса» находится в строке 174 файла /system/core/Common.php.

Похоже, что Codeigniter пытается создать экземпляр my_model.php при загрузке, что, как я предполагаю, связано с тем, что файлы в папке /core используются в качестве места для расширения основных системных файлов, таких как Controller и Model. Есть ли способ остановить это? Я пытался автоматически загрузить модель, используя нативную версию Фила Стерджена. автозагрузка, но это не помогло.

/*
| -------------------------------------------------------------------
|  Native Auto-load
| -------------------------------------------------------------------
| 
| Nothing to do with cnfig/autoload.php, this allows PHP autoload to work
| for base controllers and some third-party libraries.
|
*/

function __autoload($class)
{
    if(strpos($class, 'CI_') !== 0)
    {
        @include_once( APPPATH . 'core/'. $class . EXT );
    }
}

Я понимаю, что простым способом сделать это было бы просто включить файл в начало каждой модели, в которой я хотел бы его использовать, но, очевидно, это было бы менее чем оптимально.


person GazNicoll    schedule 25.06.2012    source источник


Ответы (3)


Зачем делать MY_Model абстрактным? Вы просто можете поместить все свои функции CRUD в MY_Model и расширить свои модели из MY_Model вместо CI_Model. Нет необходимости также использовать автозагрузку, поскольку CodeIgniter позволяет вам расширить CI_Model с помощью MY_Model, если вы поместите его в основную папку.

Хорошим примером MY_Model является пример Джейми Рамбелоу. Вы найдете его здесь: https://github.com/jamierumbelow/codeigniter-base-model/< /а>

Удачи!

Ваше здоровье

Барт

person Bart Heideman    schedule 12.08.2012

Я пытаюсь настроить класс Loader, чтобы он принимал абстракции и интерфейсы.

Сначала я добавляю все свои правки в файл /application/core/MY_Loader.php:

    <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * CodeIgniter
 *
 * An open source application development framework for PHP 5.1.6 or newer
 *
 * @package     CodeIgniter
 * @author      ExpressionEngine Dev Team
 * @copyright   Copyright (c) 2008 - 2011, EllisLab, Inc.
 * @license     http://codeigniter.com/user_guide/license.html
 * @link        http://codeigniter.com
 * @since       Version 1.0
 * @filesource
 */

// ------------------------------------------------------------------------
// Joseff Betancourt - 11/14/2012 modified code by adding a autoloader and interface loader copied from model loader.

/**
 * Loader Class
 *
 * Loads views and files
 *
 * @package     CodeIgniter
 * @subpackage  Libraries
 * @author      ExpressionEngine Dev Team
 * @category    Loader
 * @link        http://codeigniter.com/user_guide/libraries/loader.html
 */
class MY_Loader extends CI_Loader {

    // All these are set automatically. Don't mess with them.
    /**
     * Nesting level of the output buffering mechanism
     *
     * @var int
     * @access protected
     */

    protected $_ci_abstracts_paths      = array();
    /**
     * List of paths to load models from
     *
     * @var array
     * @access protected
     */
    protected $_ci_interfaces_paths     = array();
    /**
     * List of paths to load helpers from
     *
     * @var array
     * @access protected
     */

    protected $_ci_abstracts            = array();
    /**
     * List of loaded interfaces
     *
     * @var array
     * @access protected
     */
    protected $_ci_interfaces           = array();
    /**
     * List of loaded helpers
     *
     * @var array
     * @access protected
     */

    /**
     * Constructor
     *
     * Sets the path to the view files and gets the initial output buffering level
     */

    function __construct()
    {
        parent::__construct();
        $this->_ci_abstracts_paths = array(APPPATH);
        $this->_ci_interfaces_paths = array(APPPATH);
        log_message('debug', "Loader Class Initialized");
    }

    // --------------------------------------------------------------------

    /**
     * Initialize the Loader
     *
     * This method is called once in CI_Controller.
     *
     * @param   array
     * @return  object
     */
    public function initialize()
    {

        $this->_ci_abstracts = array();
        $this->_ci_interfaces = array();
        $this->_ci_autoloader();

        return $this;
    }

    // --------------------------------------------------------------------

    /**
     * Abstracts Loader
     *
     * This function lets users load and instantiate models.
     *
     * 11/14/2012 - Joseff Betancourt - Cloned from Models
     *
     * @param   string  the name of the class
     * @param   string  name for the abstract
     * @param   bool    database connection
     * @return  void
     */
    public function abstracts($abstracts, $name = '', $db_conn = FALSE)
    {
        if (is_array($abstracts))
        {
            foreach ($abstracts as $babe)
            {
                $this->abstracts($babe);
            }
            return;
        }

        if ($abstracts == '')
        {
            return;
        }

        $path = '';

        // Is the abstracts in a sub-folder? If so, parse out the filename and path.
        if (($last_slash = strrpos($abstracts, '/')) !== FALSE)
        {
            // The path is in front of the last slash
            $path = substr($abstracts, 0, $last_slash + 1);

            // And the model name behind it
            $abstracts = substr($abstracts, $last_slash + 1);
        }

        if ($name == '')
        {
            $name = $abstracts;
        }

        if (in_array($name, $this->_ci_abstracts, TRUE))
        {
            return;
        }

        $CI =& get_instance();
        if (isset($CI->$name))
        {
            show_error('The model name you are loading is the name of a resource that is already being used: '.$name);
        }

        $abstracts = strtolower($abstracts);

        foreach ($this->_ci_abstracts_paths as $mod_path)
        {
            if ( ! file_exists($mod_path.'abstracts/'.$path.$abstracts.'.php'))
            {
                continue;
            }

            if ($db_conn !== FALSE AND ! class_exists('CI_DB'))
            {
                if ($db_conn === TRUE)
                {
                    $db_conn = '';
                }

                $CI->load->database($db_conn, FALSE, TRUE);
            }

            if ( ! class_exists('CI_Abstracts'))
            {
                load_class('Abstracts', 'core');
            }

            require_once($mod_path.'abstracts/'.$path.$abstracts.'.php');

            $abstracts = ucfirst($abstracts);

            $CI->$name = new $abstracts();

            $this->_ci_abstracts[] = $name;
            return;
        }

        // couldn't find the abstracts
        show_error('Unable to locate the abstracts you have specified: '.$abstracts);
    }

    // --------------------------------------------------------------------

    /**
     * Interface Loader
     *
     * This function lets users load and instantiate interfaces.
     *
     * 11/14/2012 - Joseff Betancourt - Cloned from Models
     *
     * @param   string  the name of the class
     * @param   string  name for the interface
     * @param   bool    database connection
     * @return  void
     */
    public function interfaces($interfaces, $name = '', $db_conn = FALSE)
    {
        if (is_array($interfaces))
        {
            foreach ($interfaces as $babe)
            {
                $this->interfaces($babe);
            }
            return;
        }

        if ($interfaces == '')
        {
            return;
        }

        $path = '';

        // Is the abstracts in a sub-folder? If so, parse out the filename and path.
        if (($last_slash = strrpos($interfaces, '/')) !== FALSE)
        {
            // The path is in front of the last slash
            $path = substr($interfaces, 0, $last_slash + 1);

            // And the model name behind it
            $interfaces = substr($interfaces, $last_slash + 1);
        }

        if ($name == '')
        {
            $name = $interfaces;
        }

        if (in_array($name, $this->_ci_interfaces, TRUE))
        {
            return;
        }

        $CI =& get_instance();
        if (isset($CI->$name))
        {
            show_error('The interface name you are loading is the name of a resource that is already being used: '.$name);
        }

        $interfaces = strtolower($interfaces);

        foreach ($this->_ci_interfaces_paths as $mod_path)
        {
            if ( ! file_exists($mod_path.'interfaces/'.$path.$interfaces.'.php'))
            {
                continue;
            }

            if ($db_conn !== FALSE AND ! class_exists('CI_DB'))
            {
                if ($db_conn === TRUE)
                {
                    $db_conn = '';
                }

                $CI->load->database($db_conn, FALSE, TRUE);
            }

            if ( ! class_exists('CI_Interfaces'))
            {
                load_class('Interfaces', 'core');
            }

            require_once($mod_path.'interfaces/'.$path.$interfaces.'.php');

            $interfaces = ucfirst($interfaces);

            $CI->$name = new $interfaces();

            $this->_ci_interfaces[] = $name;
            return;
        }

        // couldn't find the interfaces
        show_error('Unable to locate the interfaces you have specified: '.$interfaces);
    }

    // --------------------------------------------------------------------


    /**
     * Autoloader
     *
     * The config/autoload.php file contains an array that permits sub-systems,
     * libraries, and helpers to be loaded automatically.
     *
     * @param   array
     * @return  void
     */
    private function _ci_autoloader()
    {
        // Abstracts models
        if (isset($autoload['abstracts']))
        {
            $this->model($autoload['abstracts']);
        }

        // Interfaces models
        if (isset($autoload['interfaces']))
        {
            $this->model($autoload['interfaces']);
        }

    }

    // --------------------------------------------------------------------

}

/* End of file Loader.php */
/* Location: ./system/core/Loader.php */

Затем я копирую основной файл Model.php в Abstracts.php и Interfaces.php (замените слово Model на или) и помещаю их в папку application/core/.

В автозагрузку я добавил

/*
| -------------------------------------------------------------------
|  Auto-load Interfaces
| -------------------------------------------------------------------
| Prototype:
|
|   $autoload['interfaces'] = array('interface1', 'interface2');
|
*/

$autoload['interfaces'] = array();


/*
| -------------------------------------------------------------------
|  Auto-load Abstracts
| -------------------------------------------------------------------
| Prototype:
|
|   $autoload['abstracts'] = array('abstract1', 'abstract2');
|
*/

$autoload['abstracts'] = array();

и, наконец, я добавил каталог в папку приложения для рефератов и интерфейсов. Еще не полностью доказано, но я думаю, что это более целостный подход, позволяющий человеку загружать аннотацию, когда это необходимо для ссылки.

Также вы должны создать реферат внутри абстрактной папки следующим образом:

abstract class MY_Model extends CI_Model
{

blah 

}
person Joseff    schedule 15.11.2012
comment
github.com/Joseffb/CIAI.git — это код, который я собрал. Надеюсь, это может помочь, и люди могут внести свой вклад во все, что я испортил. - person Joseff; 15.11.2012
comment
Просто чтобы уточнить... Вам действительно нужно взломать (или расширить) CORE, чтобы заставить это работать на CI? FML, почему бы просто не использовать FuelPHP...?? или что-то, что действительно поддерживает распространенные практики ООП? Зачем прилагать столько усилий? - person rckehoe; 22.09.2013

Сохраните файл в /application/core/MY_model.php:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class MY_model extends CI_Model
{
    public function __construct()
    {
        parent::__construct();
    }

    // Return all records in the table
    public function get_all($table)
    {
        $q = $this->db->get($table);
        if($q->num_rows() > 0)
        {
            return $q->result();
        }
        return array();
    }

    // Return only one row
    public function get_row($table,$primaryfield,$id)
    {
        $this->db->where($primaryfield,$id);
        $q = $this->db->get($table);
        if($q->num_rows() > 0)
        {
            return $q->row();
        }
        return false;
    }

    // Return one only field value
    public function get_data($table,$primaryfield,$fieldname,$id)
    {
        $this->db->select($fieldname);
        $this->db->where($primaryfield,$id);
        $q = $this->db->get($table);
        if($q->num_rows() > 0)
        {
            return $q->result();
        }
        return array();
    }

    // Insert into table
    public function add($table,$data)
    {
        return $this->db->insert($table, $data);
    }

    // Update data to table
    public function update($table,$data,$primaryfield,$id)
    {
        $this->db->where($primaryfield, $id);
        $q = $this->db->update($table, $data);
        return $q;
    }

    // Delete record from table
    public function delete($table,$primaryfield,$id)
    {
        $this->db->where($primaryfield,$id);
        $this->db->delete($table);
    }

    // Check whether a value has duplicates in the database
    public function has_duplicate($value, $tabletocheck, $fieldtocheck)
    {
        $this->db->select($fieldtocheck);
        $this->db->where($fieldtocheck,$value);
        $result = $this->db->get($tabletocheck);

        if($result->num_rows() > 0) {
            return true;
        }
        else {
            return false;
        }
    }

    // Check whether the field has any reference from other table
    // Normally to check before delete a value that is a foreign key in another table
    public function has_child($value, $tabletocheck, $fieldtocheck)
    {
        $this->db->select($fieldtocheck);
        $this->db->where($fieldtocheck,$value);
        $result = $this->db->get($tabletocheck);

        if($result->num_rows() > 0) {
            return true;
        }
        else {
            return false;
        }
    }

    // Return an array to use as reference or dropdown selection
    public function get_ref($table,$key,$value,$dropdown=false)
    {
        $this->db->from($table);
        $this->db->order_by($value);
        $result = $this->db->get();

        $array = array();
        if ($dropdown)
            $array = array("" => "Please Select");

        if($result->num_rows() > 0) {
            foreach($result->result_array() as $row) {
            $array[$row[$key]] = $row[$value];
            }
        }
        return $array;
    }
}

затем расширить вот так

class any_model extends MY_Model
{
    public function __construct()
    {
        parent::__construct();
    }
}
person Abdul Manan    schedule 25.05.2015