2011-02-23 10 views
7

tengo el siguiente código en el archivo llamado AbstractClass.php en la carpeta libraries¿Cómo se agrega la biblioteca de clases abstractas en el marco Codeigniter?

abstract class AbstractClass { 
    abstract protected doSomething(); 
} 

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

} 

Cuando intento cargar el AbstractClass de controllers de la siguiente manera:

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

me sale Unable to load the requested class: AbstractClass error.

¿Qué estoy haciendo mal? ¿Debería simplemente incluir el archivo en lugar de cargarlo?

Gracias

+0

¿Por qué estás cargando la clase abstracta en lugar de uno en concreto? – Sarfraz

+0

porque recibo un error diferente cuando hago eso. – Cory

+0

Las clases abstractas no se pueden crear instancias. Creo que Codeigniter, IIRC, intenta crear una instancia para asignar como atributo de '$ this', ¿sí? Probablemente deberías pasar al error con la clase concreta; tal vez podamos arreglar eso. – erisco

Respuesta

14

Bueno, obviamente no se puede cargar una clase abstracta directamente ya que esto va en contra del punto de una clase abstracta.

Puede poner una clase abstracta en un archivo junto con otra biblioteca, pero eso es un poco inútil y va en contra del estándar de "un archivo de una clase" que sugieren CI (y todos los buenos estándares).

Puede incluir este archivo con include() en sus archivos de biblioteca, o configurar una función __autoload() para que lo haga por usted. El mejor lugar para una __autoload() es la parte inferior de config.php.

+1

Hola, Usted ha dicho cuál es el problema y la mitad de la solución que pude entender. Please Phil (con todo el respeto que puedo dar por el trabajo que has hecho y dado a la comunidad) perdón, Todavía no pude encontrar e imaginar cómo hacer lo siguiente que has mencionado en la respuesta anterior ¡y también en tu controlador de ejemplo! que hace lo siguiente: El mejor lugar para una __autoload() es la parte inferior de config.php. En su código de ejemplo también se menciona que haga lo mismo para eliminar la línea Require. ¡Pero no hay lugar donde podría haber encontrado cómo hacerlo! Por favor explique –

1

No he visto ningún ejemplo en la web de clases abstractas con CI, así que quería confirmar que puede tener una biblioteca abstracta. Hay muy buenas razones que son fundamentales para OOP en cuanto a por qué las clases abstractas son útiles. Fundamentalmente para mí asegurarme de que las clases secundarias sigan ciertas consistencias.

Avíseme si necesita un ejemplo, ya que manualmente debe incluir la clase abstracta, asegúrese de hacerlo solo una vez para no tener problemas con la redeclaración de clases.

Tampoco se olvide si tiene una función estática o variable en la clase abstracta todavía se puede acceder a él directamente, sin tener que cargar la clase como en el siguiente

AbstractClass::static_method_you_want_to_call(); 
3

utilizo clases abstractas con CodeIgniter bibliotecas porque tengo métodos comunes que quiero que utilicen todas las clases heredadas que no tienen sentido por sí mismas. No sé si lo que voy a sugerir es la mejor práctica. Sospecho que no, pero personalmente lo encuentro útil. Así es como lo hago:

  1. Crear un nuevo clases carpeta en la carpeta de aplicación CodeIgniter.

  2. Agregue esta carpeta a la ruta. (Yo suelo hacer esto en el controlador.)

    if (!strstr(get_include_path(), APPPATH . 'classes')) { 
        ini_set('include_path', get_include_path() . ':' . APPPATH . 'classes'); 
    } 
    
  3. crear las clases abstractas, u otras clases, en las clases carpeta.

  4. crear una biblioteca de CodeIgniter extendida:

    require_once('an_abstract_class.php'); 
    class concrete_library extends an_abstract_class { 
    
  5. utilizar la biblioteca como de costumbre:

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

Que debe hacer el truco. Espero que esto sea útil.

2

Ok. Sé que esto es MUY tarde, pero estoy seguro de que muchas personas tienen preguntas sobre esto.

Esto es en realidad una limitación de la clase Loader principal, ya que intenta crear una instancia de cada uno de los elementos definidos por el primer parámetro. Como todos sabemos, las Clases abstractas, por su propia definición, son Abstractas y NO PUEDEN crearse instancias. Entonces, ¿cómo podemos evitar esto?

Pero lo más importante: ¿Cómo lo solucionamos mientras cumplimos con los estándares de CodeIgniter?

Como recién comencé a usar CodeIgniter, no puedo decir con certeza cómo se manejaron las extensiones principales en el pasado. Sin embargo, en la versión más reciente, el marco CodeIgniter le permitirá extender y anular sus clases principales Prefijando el nombre de archivo con su Prefijo de subclase definido (en la mayoría de los casos "MY_") seguido del nombre del archivo que planea extender.

*/aplicación/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(); 
    } 
} 
?> 

Es muy probable que si usted sabe cómo utilizar clases abstractas, ya sabes lo que esto hace. Básicamente, esta clase ahora hereda todas las propiedades y métodos de la clase CI_Loader original. El fragmento de código anterior es técnicamente un duplicado exacto de la clase de cargador original, pero lo más importante aquí es que ahora esta clase se hará cargo de todos los métodos de carga en lugar del original.

Ahora todo lo que tenemos que hacer es proporcionar la clase de cargador con los medios para saber si está cargando e instanciando una clase concreta, o si simplemente está incluyendo una clase abstracta.

Hay dos métodos que manejan la carga de cualquier Bibliotecas:

Método 1) public function library
Método 2) protected function _ci_load_class

Método 1 maneja el procesamiento de todos los parámetros que se le pasan por iteración a través de sí mismo si el primer parámetro es una matriz, se asegura de que los datos proporcionados estén limpios y evita que se tomen acciones si no se cumplen ciertos criterios.

Método 2 trata la carga real de los activos necesarios, manejo de errores, etc.

Podemos reemplazar el comportamiento de los métodos 1 y 2 mediante la redefinición de ellos dentro de nuestra nueva clase MY_Loader. Lo he hecho creando réplicas casi exactas de los métodos originales, pero con la adición de un 4º parámetro que, cuando sea verdadero, evitará que el cargador cree una instancia de la clase de biblioteca definida en el segundo método. También incluí un método adicional public function abstract_library que le permitirá definir explícitamente la Biblioteca como Resumen en forma abreviada.

El siguiente es el MY_Loader.clase php en su totalidad. Esto no afectará ninguna llamada existente al método de la biblioteca.

Espero que esto ayude!

*/aplicación/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); 
     } 
    } 
} 
?> 

Cargando una biblioteca abstracta:

<?php 
$this->load->library("My_Abstract_Library", NULL, NULL, true); 
/* -- OR -- */ 
$this->load->abstract_library("My_Abstract_Library"); 
?> 
+0

Vale la pena señalar que dado que las clases abstractas no se pueden crear instancias desde la clase de cargador, pasar $ params o $ object_name no hará nada y no se debe utilizar en un método de biblioteca tradicional. Si desea pasar parámetros al constructor de su clase abstracta, hágalo desde la biblioteca extendida. – maiorano84

Cuestiones relacionadas