php - español - ellislab codeigniter
Clases personalizadas en CodeIgniter (6)
CodeIgniter no es realmente compatible con objetos reales. Todas las bibliotecas, modelos y demás, son como Singletons.
Hay 2 maneras de ir, sin cambiar la estructura de CodeIgniter.
Solo incluye el archivo que contiene la clase y créelo.
Use el método load-> library o load_class (), y simplemente cree nuevos objetos. La desventaja de esto, es que siempre generará 1 objeto adicional, que simplemente no necesita. Pero eventualmente los métodos de carga también incluirán el archivo.
Otra posibilidad, que requerirá un trabajo extra, es hacer una biblioteca de User_Factory. Luego puede simplemente agregar el objeto en la parte inferior del archivo y crear nuevas instancias de él desde la fábrica.
Yo mismo soy un gran fan del patrón Factory, pero es una decisión que debes tomar tú mismo.
Espero que esto le haya ayudado, si tiene alguna pregunta que esté más relacionada con la implementación, háganoslo saber a nosotros.
Parece que este es un problema muy común para los principiantes con CodeIgniter, pero ninguna de las soluciones que he encontrado hasta ahora parece ser muy relevante para mi problema. Como dice el tema, estoy tratando de incluir una clase personalizada en CodeIgniter.
Estoy tratando de crear varios objetos de la clase a continuación y colocarlos en una matriz, por lo que necesito que la clase esté disponible para el modelo.
He intentado usar las funciones load (library-> load (''myclass'') dentro de CodeIgniter que funciona, excepto que intenta crear un objeto de la clase fuera del modelo primero. Esto obviamente es un problema ya que el constructor espera varias parámetros
Las soluciones que he encontrado hasta ahora es
- Un simple php incluye lo que parece estar bien, pero como soy nuevo en CodeIgniter, quiero asegurarme de que lo mantengo lo más posible.
- Crear una "clase envoltura" como se sugiere here , sin embargo, no estoy seguro de cómo implementaría esto.
La clase que 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();
Codeigniter tiene una función común para instanciar 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 cómo se usa es cuando se llama a la función show_404 () .
Después de 18 horas logré incluir una biblioteca en mi control sin inicialización (el constructor era el problema, debido a eso y no pude usar el código estándar $this->load->library()
). Siga la https://.com/a/21858556/4701133 . Tenga en cuenta que para una mayor inicialización de la clase nativa, use $date = new /DateTime()
con barra diagonal al frente, de lo contrario, ¡la función generará un error!
Después de una breve búsqueda en Google, me inspiré para crear mi propia clase de autocargador. Es un poco pirateado, ya que utilizo la biblioteca personalizada de Codeigniter para realizar la carga automática, pero para mí esta es la mejor manera, que conozco, de cargar todas las clases que requiero, sin comprometer la filosofía de mi arquitectura de aplicación. , para encajarlo en el modo Codeigniter de hacer las cosas. Algunos podrían argumentar que Codeigniter no es el marco adecuado para mí y eso podría ser cierto, pero estoy probando cosas y jugando con varios marcos y mientras trabajo en CI, se me ocurrió esta solución. 1. Cargue automáticamente la nueva biblioteca personalizada editando applicaion / config / autoload.php para incluir:
$autoload[''libraries''] = array(''my_loader'');
y cualquier otra biblioteca que pueda necesitar. 2. Luego 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á una vez todos los archivos .php dentro de las carpetas application / service & application / models / dto. Advertencia: las carpetas no deben tener un 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;
}
}
Incluir un archivo de clase no es un mal enfoque.
En nuestros proyectos, hacemos lo mismo, agregamos otra capa a MVC, y eso es una capa de servicio que los controladores llaman y el servicio llama al modelo. Introdujimos esta capa para agregar la lógica de negocios por separado.
Hasta ahora, lo hemos estado utilizando, y nuestro producto también se ha hecho grande, y aún así no encontramos dificultades con la decisión de incluir archivos que habíamos hecho en el pasado.
Si tiene la versión de PHP> = 5.3, puede utilizar los espacios de nombres y las funciones de carga automática .
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 Usuario en el directorio modelo. (modelos / User.php)
<?php
namespace models; // set namespace
if ( ! defined(''BASEPATH'')) exit(''No direct script access allowed'');
class User{
...
}
Y en lugar de un 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 solo asegúrese de llamar al 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();