2012-03-01 17 views
16

Parece que este es un problema muy común para principiantes con CodeIgniter, pero ninguna de las soluciones que he encontrado hasta ahora parece muy relevante para mi problema. Al igual que el tema dice que estoy tratando de incluir una clase personalizada en CodeIgniter.Clases personalizadas en CodeIgniter

Estoy tratando de crear varios objetos de la clase a continuación y colocarlos en una matriz, por lo tanto, necesito que la clase esté disponible para el modelo.

He intentado usar las funciones load (library-> load ('myclass') dentro de CodeIgniter que funcionan, excepto que primero intenta crear un objeto de la clase fuera del modelo. Esto obviamente es un problema desde el constructor espera que varios parámetros.

las soluciones que he encontrado hasta ahora es

  1. Un simple php incluyen lo que parece bastante bien, pero ya que soy nuevo en CodeIgniter quiero para asegurarse de que yo m apegándose a él tanto como posible.
  2. Creando una "clase contenedora" como se sugiere here, sin embargo no estoy seguro de cómo implementaría esto.

La clase quiero incluir, User.php

<?php if (! defined('BASEPATH')) exit('No direct script access allowed'); 
class User{ 
    public $ID = 0; 
    public $username = 0; 
    public $access_lvl = 0; 
    public $staff_type = 0; 
    public $name = 0;  

    public function __construct($ID, $username, $access_lvl, $staff_type, $name) 
    { 
     $this->ID = $ID; 
     $this->username = $username; 
     $this->access_lvl = $access_lvl; 
     $this->staff_type = $staff_type; 
     $this->name = $name; 
    } 

    public function __toString() 
    { 
     return $this->username; 
    } 
} 
?> 

Método (Modelo), que necesita el User.php

function get_all_users() 
{ 
    $query = $this->db->get('tt_login'); 
    $arr = array(); 

    foreach ($query->result_array() as $row) 
    { 
     $arr[] = new User 
     (
      $row['login_ID'], 
      $row['login_user'], 
      $row['login_super'], 
      $row['crew_type'], 
      $row['login_name'] 
     ); 
    }  

    return $arr; 
} 

Y, finalmente, el controlador ,

function index() 
{ 
     $this->load->library('user'); 
     $this->load->model('admin/usersmodel', '', true);    

     // Page title 
     $data['title'] = "Some title"; 
     // Heading 
     $data['heading'] = "Some heading"; 
     // Data (users) 
     $data['users'] = $this->usersmodel->get_all_users(); 

Respuesta

15

Si tiene la versión de PHP> = 5.3 se puede tomar uso de espacios de nombres y carga automática características.

Una biblioteca de autocargador simple en la carpeta de la biblioteca.

<?php 
class CustomAutoloader{ 

    public function __construct(){ 
     spl_autoload_register(array($this, 'loader')); 
    } 

    public function loader($className){ 
     if (substr($className, 0, 6) == 'models') 
      require APPPATH . str_replace('\\', DIRECTORY_SEPARATOR, $className) . '.php'; 
    } 

} 
?> 

El objeto de usuario en el modelo dir. (modelos/user.php)

<?php 
namespace models; // set namespace 
if (! defined('BASEPATH')) exit('No direct script access allowed'); 
class User{ 
... 
} 

Y en vez de nuevo usuario ... nuevos modelos \ Usuario (...)

function get_all_users(){ 
    .... 
    $arr[] = new models\User(
    $row['login_ID'], 
    $row['login_user'], 
    $row['login_super'], 
    $row['crew_type'], 
    $row['login_name'] 
    ); 
    ... 
} 

Y en el controlador sólo asegúrese de llamar a la customautoloader así:

function index() 
{ 
     $this->load->library('customautoloader'); 
     $this->load->model('admin/usersmodel', '', true);    

     // Page title 
     $data['title'] = "Some title"; 
     // Heading 
     $data['heading'] = "Some heading"; 
     // Data (users) 
     $data['users'] = $this->usersmodel->get_all_users(); 
+0

Gracias, funcionó como un encanto. –

+1

¿Cuáles son las ramificaciones de usar esto sin espacio de nombres? ¿O el espacio de nombres nos permite trabajar dentro de la estructura de archivos en el servidor donde hemos definido nuestras clases personalizadas? – David

3

Incluir un archivo de clase no es un mal enfoque.

En nuestros proyectos, hacemos lo mismo, agregamos otra capa a MVC, y esa es una capa de servicio que los controladores llaman y el servicio llama al modelo. Presentamos esta capa para agregar Business Logic por separado.

Hasta ahora, hemos estado usándolo, y nuestro producto también ha crecido demasiado, y todavía no encontramos dificultad con la decisión de incluir archivos que habíamos hecho en el pasado.

+3

@itachi: que lo que te parece, no es necesario, el mundo ve lo mismo. Mi respuesta es dar confianza al usuario que incluir un archivo directamente no es una idea errónea. :) – linuxeasy

+0

básicamente eso es lo que haces en cualquier otro idioma, incluido Java. La única diferencia es que los llamas 'importados' y aquí los llamas 'includes' – linuxeasy

1

Codeigniter tiene una función común para crear instancias de clases individuales.

Se llama load_class(), que se encuentra en /system/core/Common.php

La función;

/** 
* Class registry 
* 
* This function acts as a singleton. If the requested class does not 
* exist it is instantiated and set to a static variable. If it has 
* previously been instantiated the variable is returned. 
* 
* @access public 
* @param string the class name being requested 
* @param string the directory where the class should be found 
* @param string the class name prefix 
* @return object 
*/ 

La firma es

load_class($class, $directory = 'libraries', $prefix = 'CI_') 

Un ejemplo de ello es que se utiliza cuando se llama al show_404() función.

+2

Por lo que puedo decir, ¿me queda también un objeto extra fuera del modelo con este enfoque? A menos que haya una manera de evitar esto, supongo que tendré que buscar el estándar incluir. –

6

CodeIgniter realmente no admite objetos reales. Todas las bibliotecas, modelos y demás, son como Singletons.

Hay 2 formas de hacerlo, sin cambiar la estructura de CodeIgniter.

  1. Solo incluya el archivo que contiene la clase y generela.

  2. Utilice el método load-> library o load_class(), y simplemente cree nuevos objetos. La desventaja de esto, es que siempre generará 1 objeto extra, que simplemente no necesita. Pero eventualmente los métodos de carga también incluirán el archivo.

Otra posibilidad, que requerirá un trabajo adicional, es crear una biblioteca User_Factory. A continuación, puede agregar el objeto en la parte inferior del archivo y crear instancias nuevas desde la fábrica.

Soy un gran admirador del patrón Factory, pero es una decisión que debe tomar usted mismo.

Espero que esto lo haya ayudado, si tiene alguna pregunta que esté más relacionada con la implementación, solo avísenos.

+2

¿Podría vincularme algún ejemplo de este enfoque? –

0

Después de una breve búsqueda en Google, que se inspiró para hacer mi propia clase cargador automático. Es un poco complicado, ya que utilizo una biblioteca Codeigniter personalizada para preformar la carga automática, pero para mí es la mejor manera, que yo sepa, de cargar todas las clases, lo requiero, sin comprometer la filosofía de mi arquitectura de aplicaciones. , para encajarlo en la forma de hacer Codeigniter. Algunos podrían argumentar que Codeigniter no es el marco correcto para mí y que podría ser cierto, pero estoy probando cosas y jugando con varios marcos y trabajando en CI, se me ocurrió esta solución. 1. Auto-carga de la biblioteca nueva costumbre editando applicaion/config/autoload.php para incluir:

$autoload['libraries'] = array('my_loader'); 

y cualquier otra biblioteca que pueda necesitar. 2. A continuación, agregue la clase de biblioteca My_loader. Esta clase se cargará en cada solicitud y cuando se ejecute su constructor, buscará recursivamente en todas las subcarpetas y requerirá_unce todos los archivos .php dentro de la aplicación/servicio & application/models/dto folders.Advertencia: carpetas no deben tener punto en el nombre, de lo contrario la función fallará

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

class My_loader { 

    protected static $_packages = array(
      'service', 
      'models/dto' 
      ); 

    /** 
    * Constructor loads service & dto classes 
    * 
    * @return void 
    */ 
    public function __construct($packages = array('service', 'models/dto')) 
    { 
     // files to be required 
     $toBeRequired = array(); 

     // itrate through packages 
     foreach ($packages as $package) { 
      $path = realpath(APPPATH . '/' . $package . '/'); 
      $toBeRequired = array_merge($toBeRequired, $this->findAllPhpFiles($path)); 
     } 

     /** 
     * Require all files 
     */ 
     foreach ($toBeRequired as $class) { 
      require_once $class; 
     } 
    } 

    /** 
    * Find all files in the folder 
    * 
    * @param string $package 
    * @return string[] 
    */ 
    public function findAllPhpFiles($path) 
    { 
     $filesArray = array(); 
     // find everithing in the folder 
     $all = scandir($path); 
     // get all the folders 
     $folders = array_filter($all, get_called_class() . '::_folderFilter'); 
     // get all the files 
     $files = array_filter($all, get_called_class() . '::_limitationFilter'); 

     // assemble paths to the files 
     foreach ($files as $file) { 
      $filesArray[] = $path . '/' . $file; 
     } 
     // recursively go through all the sub-folders 
     foreach ($folders as $folder) { 
      $filesArray = array_merge($filesArray, $this->findAllPhpFiles($path . '/' . $folder)); 
     } 

     return $filesArray; 
    } 

    /** 
    * Callback function used to filter out array members containing unwanted text 
    * 
    * @param string $string 
    * @return boolean 
    */ 
    protected static function _folderFilter($member) { 
     $unwantedString = '.'; 
     return strpos($member, $unwantedString) === false; 
    } 

    /** 
    * Callback function used to filter out array members not containing wanted text 
    * 
    * @param string $string 
    * @return boolean 
    */ 
    protected static function _limitationFilter($member) { 
     $wantedString = '.php'; 
     return strpos($member, $wantedString) !== false; 
    } 
} 
0

Después de 18 horas me las arreglé para incluir una biblioteca en mi control sin inicialización (el constructor fue el problema, debido a que y pude' t use el codeiginiter estándar $this->load->library()). Siga el https://stackoverflow.com/a/21858556/4701133. Tenga en cuenta que para la inicialización de la clase nativa utilice $date = new \DateTime() con barra diagonal en el frente, de lo contrario la función generará un error.

Cuestiones relacionadas