Foros del Web » Programando para Internet » PHP » Frameworks y PHP orientado a objetos »

Duda con FrontController

Estas en el tema de Duda con FrontController en el foro de Frameworks y PHP orientado a objetos en Foros del Web. Buenos días colegas, estaba siguiendo un tutorial de mvc y me toca la parte del frontcontroller... pues ahora lo tengo así y funciona: Código PHP: ...
  #1 (permalink)  
Antiguo 07/01/2011, 08:51
Avatar de cesarpunk  
Fecha de Ingreso: enero-2008
Ubicación: Lima
Mensajes: 943
Antigüedad: 16 años, 3 meses
Puntos: 9
Duda con FrontController

Buenos días colegas, estaba siguiendo un tutorial de mvc y me toca la parte del frontcontroller... pues ahora lo tengo así y funciona:

Código PHP:

class FrontController {

    public static function 
main() {
            
        require 
'config/Config.class.php';
        require 
'config/Db.class.php';
        require 
'config/View.php';
        require 
'config/Controller.php';
        require 
'config/ActiveTable.php';
        
        require 
'modelos/Clientes.class.php';
        
        require 
'config/config.php';
        
        
        if(! empty(
$_GET['controlador']))
              
$controllerName $_GET['controlador'] . 'Controller';
        else
              
$controllerName "IndexController";
        
        if(! empty(
$_GET['accion']))
              
$actionName $_GET['accion'];
        else
              
$actionName "index";
        
        
$controllerPath $config->get('controllersFolder') . $controllerName '.php';
            

        if(
is_file($controllerPath))
              require 
$controllerPath;
        else
              die(
'El controlador no existe - 404 not found');
        

        if (
is_callable(array($controllerName$actionName)) == false) {
        
            
trigger_error ($controllerName '->' $actionName '` no existe'E_USER_NOTICE);
            return 
false;
            
        }
        
        
$controller = new $controllerName();
        
$controller->$actionName();
        
    }
    

Mi duda es que si es necesario invocar a todas las clases del modelo Clientes.php, Productos.php, Factura.php, Detalle.php, etc en ese mismo archivo... he visto los tutoriales y parece que no los invocan , si se me ocurre quitar esa clase me sale el error Class 'Clientes' not found...

No estoy seguro si lo estoy haciendo bien o si hay alguna manera de invocar diferentes clases cuando se las necesite, espero me puedan guiar.

Saludos.
__________________
Quitenme la vida pero no la bebida.
  #2 (permalink)  
Antiguo 07/01/2011, 10:15
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 17 años, 10 meses
Puntos: 2135
Respuesta: Duda con FrontController

La idea es que en tus clases hagas un require_once, o uses el autoloader para cargar las clases que necesites, no es buena idea que tengas que cargar todas las clases las uses o no en tu FrontController.

Saludos.
  #3 (permalink)  
Antiguo 07/01/2011, 10:23
Avatar de Heli0s  
Fecha de Ingreso: abril-2010
Mensajes: 789
Antigüedad: 14 años
Puntos: 40
Respuesta: Duda con FrontController

Como dice GatorV, las clases que dependan de otras clases SIEMPRE deben tener un require_once o include_once en el mismo archivo de la clase, asi te garantizas que en caso de que tengas que reutilizarlas en otro proyecto, sabes que ya tendran el include, y no tendrás que estar mirando que clases incluistes o no en tu frontController, la idea es sencilla, una clase necesita a otra para funcionar bien? require_once.

Un saludo
  #4 (permalink)  
Antiguo 07/01/2011, 10:41
Avatar de cesarpunk  
Fecha de Ingreso: enero-2008
Ubicación: Lima
Mensajes: 943
Antigüedad: 16 años, 3 meses
Puntos: 9
Respuesta: Duda con FrontController

Gracias por la recomendación, una última consulta... el autoloader es el __autoload() verdad? como lo aplicaría en un controlador?

Código PHP:

<?php
require_once 'config/View.php';
require_once 
'config/Controller.php';
require_once 
'modelos/Clientes.class.php';

class 
ClientesController extends Controller {
   public function 
__construct() {
   
   }
   
   public function 
listaClientes() {
        
$clientes = new Clientes();
       
        
$data = array();
        
$data['Clientes'] = $clientes->findAll();
        
        
$view = new View();
        
$view->setData$data );
        
$view->setTemplate'vistas/listarClientes.php' );
        
$view->setLayout'vistas/mainLayout.php' );
        
        
$view->render();
   }

}
__________________
Quitenme la vida pero no la bebida.
  #5 (permalink)  
Antiguo 07/01/2011, 10:55
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 17 años, 10 meses
Puntos: 2135
Respuesta: Duda con FrontController

Puedes usar __autoload o spl_autoload_register y la tienes que implementar en donde quieras, el chiste es que este declarada antes de que inicies toda tu aplicación para que así puedas cargar todas tus clases.

Saludos.
  #6 (permalink)  
Antiguo 07/01/2011, 11:56
Avatar de cesarpunk  
Fecha de Ingreso: enero-2008
Ubicación: Lima
Mensajes: 943
Antigüedad: 16 años, 3 meses
Puntos: 9
Respuesta: Duda con FrontController

Chequeando el manual, he visto una clase muy interesante:

Código PHP:

<?php
class autoload_autoloader {
    public static 
$instance;
    private 
$_src=array('controladores/''modelos/''config/');
    private 
$_ext=array('.php''.class.php''Controller.php');
    
    public static function 
init(){
        if(
self::$instance==NULL){
            
self::$instance=new self();
        }
        return 
self::$instance;
    }

    private function 
__construct(){
        
spl_autoload_register(array($this'clean'));
        
spl_autoload_register(array($this'dirty'));
    }
    
    private function 
clean($class){
        global 
$docroot;
        
$class=str_replace('_''/'$class);
        
spl_autoload_extensions(implode(','$this->_ext));
        foreach(
$this->_src as $resource){
            
set_include_path($docroot $resource);
            
spl_autoload($class);
        }
    }
    
    private function 
dirty($class){
        global 
$docroot;
        
$class=str_replace('_''/'$class);
        foreach(
$this->_src as $resource){
            foreach(
$this->_ext as $ext){
                @include(
$docroot $resource $class $ext);
            }
        }
        
spl_autoload($class);
    }

}

?>
Supongo que la idea es que ya no se usen los requires en las clases que la usen pero donde la inicializo? en el index de mi aplicación?... intenté asi (trabajando en localhost):

Código PHP:

$docroot 
'http://localhost/';
require 
'config/Autoloader.php';
require 
'config/FrontController.php';

autoload_autoloader::init();
FrontController::main(); 
Pero aún me sale un error Fatal error: Class 'Cliente' not found in ... Espero me puedan ayudar y disculpen por tantas preguntas
__________________
Quitenme la vida pero no la bebida.
  #7 (permalink)  
Antiguo 07/01/2011, 12:17
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 17 años, 10 meses
Puntos: 2135
Respuesta: Duda con FrontController

El document root debería de ser el path físico a tus archivos, no la URL, ya que el include trabaja sobre paths físicos no sobre urls, ya que eso te incluiría el resultado de la inclusión (si tienes activado el allow_url_fopen) y no el código PHP.

Saludos.
  #8 (permalink)  
Antiguo 07/01/2011, 12:39
Avatar de cesarpunk  
Fecha de Ingreso: enero-2008
Ubicación: Lima
Mensajes: 943
Antigüedad: 16 años, 3 meses
Puntos: 9
Respuesta: Duda con FrontController

Sip entiendo, lo cambié como dice el manual :

Código PHP:

$docroot 
$_SERVER['DOCUMENT_ROOT'] . implode('/',array_slice(explode('/',$_SERVER['PHP_SELF']),0,-2)) . '/';
require 
'config/Autoloader.php';
require 
'config/FrontController.php';

autoload_autoloader::init();
FrontController::main(); 
Eso me devuelve el C:/AppServ/www/ y he verificado el allow_url_fopen y está en On ... pero aún me sigue saliendo Fatal error: Class 'Clientes' not found in...

Que otra cosa estaría mal?
__________________
Quitenme la vida pero no la bebida.
  #9 (permalink)  
Antiguo 07/01/2011, 15:16
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 17 años, 10 meses
Puntos: 2135
Respuesta: Duda con FrontController

Revisa el path que te da, si te fijas dice Class 'Clientes' not found in, y te debe de dar el path que esta buscando.

Saludos.
  #10 (permalink)  
Antiguo 07/01/2011, 16:07
Avatar de cesarpunk  
Fecha de Ingreso: enero-2008
Ubicación: Lima
Mensajes: 943
Antigüedad: 16 años, 3 meses
Puntos: 9
Respuesta: Duda con FrontController

Bueno, al parecer faltaba el nombre de la carpeta de mi proyecto en el doc_root, pero ahora tengo un problema con las vistas ya que al parecer no las encuentran

Código:
Warning: View::include(vistas/mainLayout.tpl.php) [view.include]: failed to open stream: No such file or directory in C:\AppServ\www\prueba\config\View.php on line 36

Warning: View::include() [function.include]: Failed opening 'vistas/mainLayout.tpl.php' for inclusion (include_path='C:/AppServ/www/prueba/config/') in C:\AppServ\www\mvc_prueba\config\View.php on line 36

Peor en el controlador lo tengo asi:

Código PHP:

class ClientesController extends Controller {
   public function 
__construct() {
   
   }
   
   public function 
listaClientes() {
        
$clientes = new Clientes();
       
        
$data = array();
        
$data['Clientes'] = $clientes->findAll();
        
        
$view = new View();
        
$view->setData$data );
        
$view->setTemplate'vistas/listarClientes.tpl.php' );
        
$view->setLayout'vistas/mainLayout.tpl.php' );
        
        
$view->render();
   }
   

debo modificar algo al invocar las vistas?
__________________
Quitenme la vida pero no la bebida.
  #11 (permalink)  
Antiguo 07/01/2011, 16:53
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 17 años, 10 meses
Puntos: 2135
Respuesta: Duda con FrontController

Pues desconozco que contenga tu código de las vistas y como seleccione la carpeta que contiene la vista.

Saludos.
  #12 (permalink)  
Antiguo 07/01/2011, 17:01
Avatar de cesarpunk  
Fecha de Ingreso: enero-2008
Ubicación: Lima
Mensajes: 943
Antigüedad: 16 años, 3 meses
Puntos: 9
Respuesta: Duda con FrontController

Lo único que hace es reconocer si existe el archivo de la vista:

Código PHP:

class ViewException extends Exception {}
class 
View {
   private 
$data;
   private 
$template;
   private 
$layout;
   
   public function 
__construct() {}
   
   public function 
setData$data ) {
        if( !
is_array$data ) ) {
             throw new 
ViewException('$data no ha sido enviado ');
        }
        
$this->data $data;
   }
   
   public function 
setLayout$layout ) {
        if( !
file_exists$layout ) ) {
             throw new 
ViewException('$layout  no existe');
        }
        
        
$this->layout $layout;
   }
   
   public function 
setTemplate($template) {
        if( !
file_exists$template ) ) {
             throw new 
ViewException('$template no existe');
        }
        
        
$this->template $template;
   }
   
   public function 
render() {
        
$content $this->renderTemplate();
       
        include( 
$this->layout );
   }
   
   private function 
renderTemplate() {
        
ob_start();
        @
extract$this->dataEXTR_OVERWRITE );
        include( 
$this->template );
        
$content ob_get_clean();
        
        return 
$content;
   }

Si modifico la ruta del $view->setLayout( 'vistas/mainLayout.tpl.php' ); me sale el error "$layout no existe", osea de alguna manera si reconoce el archivo, pero parece que no encuentra la ruta
__________________
Quitenme la vida pero no la bebida.
  #13 (permalink)  
Antiguo 07/01/2011, 17:12
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 17 años, 10 meses
Puntos: 2135
Respuesta: Duda con FrontController

Pues si te fijas esta tratando de incluir tus templates desde C:\AppServ\www\prueba\config\, te recomiendo que uses PATHS absolutos para asegurarte que estas incluyendo el archivo correcto.

Saludos.
  #14 (permalink)  
Antiguo 07/01/2011, 17:23
Avatar de cesarpunk  
Fecha de Ingreso: enero-2008
Ubicación: Lima
Mensajes: 943
Antigüedad: 16 años, 3 meses
Puntos: 9
Respuesta: Duda con FrontController

Sip tienes razón Gatorv, muchas gracias denuevo.
__________________
Quitenme la vida pero no la bebida.
  #15 (permalink)  
Antiguo 12/01/2011, 12:13
Avatar de destor77  
Fecha de Ingreso: noviembre-2004
Ubicación: Gálvez, Santa Fe, Argentina
Mensajes: 2.654
Antigüedad: 19 años, 5 meses
Puntos: 43
Respuesta: Duda con FrontController

cesarpunk (muy copado tu nic punk not dead!!!),
Te cuento como lo hice yo en mi framework (que no quita que sea la manera correcta).
En el frontcontroller, solo dejo la lógica para saber que controller ejecutar y configurar algunos parametros como la ruta por defult de las vistas (mi controladores tienen una carpeta template con las vistas, en vez de tenerlas todas en un solo lugar para todos ellos, cuestion de gustos jeje).
Despues en mi clase "Controller", lo que hago es 2 cosas (que ahora que lo pienso puede ser medio redundante jeje), en el constructor tengo esto:
Código PHP:
Ver original
  1. $this->Utilidades->recursiveInclude($this->Config->get('path_root').$this->Config->get('modelsFolder'));

el método recursiveInclude es asi:
Código PHP:
Ver original
  1. public function recursiveInclude($path) {
  2.         $config = Config::singleton();     
  3.         if(!empty($path)) {    
  4.         $dir    = scandir($path);
  5.         if ( (is_array($dir)) && (count($dir) > 0) )
  6.             foreach($dir as $k => $v)
  7.             if ( !(is_dir($path.$v)) && ( file_exists($path.$v) ) && ($v != ".")  && ($v != "..") && (strtolower(end(explode(".", $v))) == 'php') )
  8.                 include_once($path.$v);
  9.             elseif ( is_dir($path.$v) && ($v != ".") && ($v != "..") && ($v != 'smarty') && ($v != '.svn'))
  10.                 recursiveInclude($path.$v."/");
  11.         }
  12.     }

que lo que hace es cargar todos los archivos php de un directorio por ejemplo "modelos".
Después en tus controladores tiene que instanciar los modelos:
Código PHP:
Ver original
  1. private $cliente;
  2.  
  3. function __construct(){
  4.   $this->cliente = new ClienteModelo();
  5. }

pero despues hice un método en el Controller que permite como CI o cake cargar de manera independiente uno o varios modelos, helpers, etc. que es asi:
Código PHP:
Ver original
  1. public function modelo($nombre) {
  2.         if(empty($nombre)) {
  3.         return false;
  4.         }
  5.  
  6.         if(is_array($nombre)) {
  7.         foreach($nombre as $modelo) {
  8.             $modelo = ucfirst($modelo);
  9.             //valido si existe el archivo del modelo
  10.             if(!empty($modelo)) {
  11.             if(file_exists($this->Config->get('root').$this->Config->get('modelsFolder').$modelo.'Model.php')) {
  12.                 //valido si no esta instanciada la clase previamente
  13.                 if(!class_exists($modelo)) {
  14.                 include_once($this->Config->get('root').$this->Config->get('modelsFolder').$modelo.'Model.php');
  15.                 $this->$modelo = new $modelo();
  16.                 }
  17.                 else {
  18.                 $this->$modelo = new $modelo();
  19.                 }
  20.  
  21.             }
  22.             else {
  23.                 $ruta = $this->Config->get('root').$this->Config->get('modelsFolder').$modelo.'Model.php';
  24.                 error_log("[".date("F j, Y, G:i")."] [Error: E_USER_NOTICE] [tipo modelos] No se encuentra el modelo: {$modelo} en {$ruta}- \n", 3,$this->Config->get('root').'/errores.log');
  25.  
  26.                 return false;
  27.             }
  28.             }
  29.         }
  30.         }
  31.         else {
  32.         //valido si existe el archivo de la libreria
  33.         $modelo = ucfirst($nombre);    
  34.         if(file_exists($this->Config->get('root').$this->Config->get('modelsFolder').$modelo.'Model.php')) {                       
  35.             //valido si no esta instanciada la clase previamente
  36.             if(!class_exists(ucfirst($modelo))) {          
  37.             include_once($this->Config->get('root').$this->Config->get('modelsFolder').$modelo.'Model.php');
  38.             $this->$modelo = new $modelo();
  39.             }
  40.             else {
  41.             $this->$modelo = new $modelo();
  42.             }          
  43.         }
  44.         else {         
  45.             $ruta = $this->Config->get('root').$this->Config->get('modelsFolder').$modelo.'Model.php';
  46.             error_log("[".date("F j, Y, G:i")."] [Error: E_USER_NOTICE] [tipo modelos]  No se encuentra el modelo: {$modelo} en {$ruta}\n", 3,$this->Config->get('root').'/errores.log');
  47.             //trigger_error("No se encuentra la libreria: {$nombre} en {$ruta}<br/>",E_USER_NOTICE);
  48.             return false;
  49.         }
  50.         }
  51.     }
con eso desde el controlador podes hacer esto:
Código PHP:
Ver original
  1. function __construct(){
  2.  $this->modelos('clientes');
  3. //o hacerlo asi:
  4. // $this->modelos(array('clientes','proveedores','otromodelo'));
  5. }
  6.  
  7. // y usarlo asi:
  8. public function index(){
  9.  $this->clientes->metodoDelModelo();
  10. }

esto que yo aplique a los modelos, podes aplicarlo a lo que te convenga, podes usar el mismo código y sólo tenes que cambiar la ruta a donde buscar y listo.
No se si es la mejor forma, pero a mi me funciona de maravillas.
Salu2
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 10:51.