簡體   English   中英

如何在Codeigniter框架中添加抽象類庫?

[英]How do you add abstract class library in the Codeigniter framework?

我在libraries文件夾中名為AbstractClass.php文件中有以下代碼

abstract class AbstractClass {
  abstract protected doSomething ();
}

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

}

當我嘗試從controllers加載AbstractClass時,如下所示:

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

我得到Unable to load the requested class: AbstractClass錯誤。

我究竟做錯了什么? 我應該只包含文件而不是加載它嗎?

謝謝

很明顯,你不能直接加載一個抽象類,因為這與抽象類的觀點相悖。

您可以將一個抽象類與另一個庫一起放在一個文件中,但這有點毫無意義,並且違背了CI(以及所有良好標准)建議的“一級一檔”標准。

您可以在庫文件中包含此文件包含include(),也可以設置__autoload()函數來為您執行此操作。 __autoload()的最佳位置是config.php的底部。

我使用帶有CodeIgniter庫的抽象類,因為我有一些常用的方法,我希望所有繼承的類都可以使用,這些方法本身就沒有意義。 我不知道我建議的是最佳做法。 我懷疑它不是,但我個人覺得它很有用。 我是這樣做的:

  1. 在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'); 

這應該夠了吧。 我希望這很有用。

好。 我知道這是遲到的,但我相信很多人對此都有疑問。

這實際上是核心Loader類的限制,因為它試圖實例化第一個參數定義的每個項目。 眾所周知,抽象類的定義是抽象的,不能實例化。 那么我們如何解決這個問題呢?

但最重要的是: 我們如何在符合CodeIgniter標准的同時解決這個問題?

由於我剛剛開始使用CodeIgniter,因此我無法確定過去如何處理Core Extensions。 但是,在最新版本中,CodeIgniter框架將允許您通過使用已定義的子類前綴(在大多數情況下為“MY_”)前綴文件名,然后是您計划擴展的文件的名稱來擴展和覆蓋其核心類。

* /應用/核心/ 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類的所有屬性和方法。 上面的代碼片段在技術上與原始Loader類完全相同,但最重要的是現在這個類將接管所有加載方法而不是原始方法。

現在我們需要做的就是為loader類提供了解它是否正在加載和實例化一個具體類的方法,或者它是否只包含一個抽象類。

有兩種方法可以處理任何庫的加載:

方法1) public function library
方法2) protected function _ci_load_class

如果第一個參數是數組,方法1通過迭代自身來處理傳遞給它的所有參數,確保提供的數據是干凈的,並且如果不滿足某些條件,則阻止采取任何操作。

方法2處理必要資產的實際加載,錯誤處理等。

我們可以通過在新的MY_Loader類中重新定義它們來覆蓋方法1和2的行為。 我通過創建原始方法的幾乎精確的副本來完成此操作,但添加了第4個參數 - 當為true時 - 將阻止Loader在第二個方法中實例化定義的庫類。 我還添加了一個額外的方法public function abstract_library ,它允許您以簡寫的方式將Library顯式定義為Abstract。

以下是MY_Loader.php類的完整內容。 這不會影響對庫方法的任何現有調用。

希望這可以幫助!

* /應用/核心/ 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");
?>

我沒有看到有關CI的抽象類Web的任何示例,所以我想確認您可以擁有一個抽象庫。 對於為什么抽象類有用,OOP有很好的理由是OOP的基礎。 從根本上說,我要確保兒童班遵循一定的一致性。

如果您需要一個示例,請告訴我,因為您手動必須包含抽象類,請確保只執行一次,這樣您就不會遇到重新聲明類的問題。

另外不要忘記,如果您在Abstract類中有靜態函數或變量,您仍然可以直接訪問它而無需加載類,如下所示

AbstractClass::static_method_you_want_to_call();

我找到了一種在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();
       }
   }

然后從Controller調用該lib。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM