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");
?>
¿Por qué estás cargando la clase abstracta en lugar de uno en concreto? – Sarfraz
porque recibo un error diferente cuando hago eso. – Cory
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