Как добавить абстрактную библиотеку классов в платформу Codeigniter? - PullRequest
7 голосов
/ 24 февраля 2011

У меня есть следующий код в файле с именем AbstractClass.php в папке libraries

abstract class AbstractClass {
  abstract protected doSomething ();
}

class ConcreteClass extends AbstractClass {
  public function doSomething () {};

}

Когда я пытаюсь загрузить AbstractClass из controllers следующим образом:

$this->load->library('AbstractClass');

Я получаю Unable to load the requested class: AbstractClass ошибку.

Что я делаю не так?Должен ли я просто включить файл вместо его загрузки?

Спасибо

Ответы [ 5 ]

14 голосов
/ 24 февраля 2011

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

Вы можете поместить абстрактный класс в файл вместе с другой библиотекой, но это немного бессмысленно и идет вразрез со стандартом "один класс один файл", который предлагает CI (и все хорошие стандарты).

Вы можете включить этот файл с помощью include () в свои файлы библиотеки или настроить функцию __autoload (), чтобы сделать это за вас.Лучшее место для __autoload () - это нижняя часть config.php.

4 голосов
/ 29 июля 2013

Я использую абстрактные классы с библиотеками CodeIgniter, потому что у меня есть общие методы, которые я хочу использовать для всех унаследованных классов, которые сами по себе бессмысленны. Я не знаю, является ли то, что я собираюсь предложить, лучшей практикой. Я подозреваю, что это не так, но лично я считаю это полезным. Вот как я это делаю:

  1. Создайте новую папку classes в папке приложения CodeIgniter.

  2. Добавить эту папку в путь. (Я обычно делаю это в контроллере.)

    if (!strstr(get_include_path(), APPPATH . 'classes')) {
        ini_set('include_path', get_include_path() . ':' . APPPATH . 'classes');
    }
    
  3. Создайте абстрактные классы или другие классы в папке classes .

  4. Создание расширенной библиотеки CodeIgniter:

    require_once('an_abstract_class.php');
    class concrete_library extends an_abstract_class {
    
  5. Используйте библиотеку как обычно:

    $this->load->library('concrete_library');
    

Это должно сработать. Я надеюсь, что это полезно.

3 голосов
/ 02 октября 2013

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

Это на самом деле ограничение основного класса Loader, поскольку он пытается создать экземпляр каждого из элементов, определенных первымпараметр.Как мы все знаем, абстрактные классы по определению являются абстрактными и не могут быть созданы.Итак, как нам обойти это?

Но самое главное: Как мы можем обойти это в соответствии со стандартами CodeIgniter?

Поскольку я только началиспользуя CodeIgniter, я не могу точно сказать, как обрабатывались Core Extensions в прошлом.Однако в самой последней версии платформа CodeIgniter позволит вам расширять и переопределять его базовые классы, добавляя префикс имени файла к определенному префиксу подкласса (в большинстве случаев «MY_»), за которым следует имя файла, который вы планируете расширять.

* / application / core / MY_Loader.php *

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

class MY_Loader extends CI_Loader{
    public function __construct(){
        parent::__construct();
    }
}
?>

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

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

Существует два метода, которые обрабатывают загрузку любых библиотек:

Метод 1) public function library
Метод 2) protected function _ci_load_class

Метод 1 обрабатывает все передаваемые ему параметры путем итерации через себя, если первый параметр является массивом, проверяет, предоставлены ли данныеявляется чистым и предотвращает выполнение каких-либо действий, если определенные критерии не выполнены.

Метод 2 обрабатывает фактическую загрузку необходимых ресурсов, обработку ошибок и т. д.

Мы можем переопределитьповедение методов 1 и 2 путем переопределения их в нашем новом классе MY_Loader.Я сделал это путем создания почти точных копий исходных методов, но с добавлением 4-го параметра, который - при значении true - не позволит загрузчику создавать экземпляр определенного класса библиотеки во втором методе.Я также включил дополнительный метод public function abstract_library, который позволит вам явным образом кратко определить библиотеку как абстрактную.

Ниже приведен класс MY_Loader.php во всей его полноте.Это не повлияет на любые существующие вызовы метода библиотеки.

Надеюсь, это поможет!

* / application / core / MY_Loader.php *

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

class MY_Loader extends CI_Loader{
    public function __construct(){
        parent::__construct();
    }
    public function library($library = '', $params = NULL, $object_name = NULL, $is_abstract=false){
        if(is_array($library)){
            foreach ($library as $class){
                $this->library($class, $params);
            }
            return;
        }

        if($library == '' OR isset($this->_base_classes[$library])){
            return FALSE;
        }

        if(!is_null($params) && ! is_array($params)){
            $params = NULL;
        }

        $this->_ci_load_class($library, $params, $object_name, $is_abstract);
    }
    public function abstract_library($library=''){
        $this->library($library, NULL , NULL, true);
    }
    protected function _ci_load_class($class, $params = NULL, $object_name = NULL, $is_abstract=false)
    {
        $class = str_replace('.php', '', trim($class, '/'));
        $subdir = '';
        if(($last_slash = strrpos($class, '/')) !== FALSE){
            $subdir = substr($class, 0, $last_slash + 1);
            $class = substr($class, $last_slash + 1);
        }
        foreach(array(ucfirst($class), strtolower($class)) as $class){
            $subclass = APPPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.'.php';
            if(file_exists($subclass)){
                $baseclass = BASEPATH.'libraries/'.ucfirst($class).'.php';

                if (!file_exists($baseclass)){
                    log_message('error', "Unable to load the requested class: ".$class);
                    show_error("Unable to load the requested class: ".$class);
                }
                if(in_array($subclass, $this->_ci_loaded_files)){
                    if(!is_null($object_name)){
                        $CI =& get_instance();
                        if(!isset($CI->$object_name)){
                            return $is_abstract ? true : $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
                        }
                    }

                    $is_duplicate = TRUE;
                    log_message('debug', $class." class already loaded. Second attempt ignored.");
                    return;
                }

                include_once($baseclass);
                include_once($subclass);
                $this->_ci_loaded_files[] = $subclass;

                return $is_abstract ? true : $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
            }
            $is_duplicate = FALSE;
            foreach ($this->_ci_library_paths as $path){
                $filepath = $path.'libraries/'.$subdir.$class.'.php';
                if(!file_exists($filepath)){
                    continue;
                }
                if(in_array($filepath, $this->_ci_loaded_files)){
                    if(!is_null($object_name)){
                        $CI =& get_instance();
                        if(!isset($CI->$object_name)){
                            return $is_abstract ? true : $this->_ci_init_class($class, '', $params, $object_name);
                        }
                    }

                    $is_duplicate = TRUE;
                    log_message('debug', $class." class already loaded. Second attempt ignored.");
                    return;
                }

                include_once($filepath);
                $this->_ci_loaded_files[] = $filepath;
                return $is_abstract ? true : $this->_ci_init_class($class, '', $params, $object_name);
            }

        } // END FOREACH

        if($subdir == ''){
            $path = strtolower($class).'/'.$class;
            return $this->_ci_load_class($path, $params, $is_abstract);
        }

        if($is_duplicate == FALSE){
            log_message('error', "Unable to load the requested class: ".$class);
            show_error("Unable to load the requested class: ".$class);
        }
    }
}
?>

Загрузка абстрактной библиотеки:

<?php
$this->load->library("My_Abstract_Library", NULL, NULL, true);
/* -- OR -- */
$this->load->abstract_library("My_Abstract_Library");
?>
1 голос
/ 25 июля 2013

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

Дайте мне знать, если вам нужен пример, поскольку вы должны вручную включить абстрактный класс, убедитесь, что вы делаете это только один раз, чтобы не возникало проблем с повторным выделением классов.

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

AbstractClass::static_method_you_want_to_call();
0 голосов
/ 26 августа 2018

Я нашел простой способ использовать абстрактные классы в Codeigniter. Просто следуйте этим шагам. Перейти в библиотеки в системной папке

  1. Создайте абстрактный класс и не связывайте его с CI, просто назовите его простым словом без CI_
  2. Создайте имя другого класса, используя то же слово, что и имя файла. Как показано в коде ниже
  3. Расширить этот класс абстрактным классом.
  4. Затем вызовите функцию абстрактного класса через ваш класс CI_class.

Система -> библиотеки -> lib.php

    abstract class B
    {

       public function lib1()
       {
           echo "This is library 1";
       }

       public function lib2()
       {
           echo "This is library 1";
       }
   }

   class CI_lib extends B
   {
       public function libs(){
        $this->lib1();
       }
   }

Затем вызовите эту библиотеку из контроллера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...