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

Solicitud de orientacion

Estas en el tema de Solicitud de orientacion en el foro de Frameworks y PHP orientado a objetos en Foros del Web. Estoy reescribiendo mis codigos y entrando mas de lleno a POO, por lo que me gustaria que me den opiniones sobre lo que estoy trabajando ...
  #1 (permalink)  
Antiguo 03/04/2011, 02:10
Avatar de Triby
Mod on free time
 
Fecha de Ingreso: agosto-2008
Ubicación: $MX->Gto['León'];
Mensajes: 10.106
Antigüedad: 15 años, 8 meses
Puntos: 2237
Solicitud de orientacion

Estoy reescribiendo mis codigos y entrando mas de lleno a POO, por lo que me gustaria que me den opiniones sobre lo que estoy trabajando para saber si voy bien o me regreso:

1- Clase principal: Aqui cargo toda la configuracion y tengo funciones generales para manejo de mensajes, errores, redirecciones, etc.
2- Clase abstractas base donde creo funciones que usan la instancia de la clase principal, con el fin de evitar al maximo el uso de global $clase; (claro, fuera de la base )
3- Clases abstractas (model, view, controller) que extienden la clase base y que incluyo solo funciones especificas para cada capa.
4- Clase especifica (model, view, controller) para cada modulo.

Ejemplo:
Código PHP:
Ver original
  1. // Clase general
  2. class principal {
  3.     private $_models = array();
  4.     public function __construct() {}
  5.     // Obtener o crear instancia de un modelo
  6.     public function getModel($model) {
  7.         if(!isset($this->_models[$model])) {
  8.             $file = "ruta/{$model}.model.php";
  9.             $class = $model . 'Model';
  10.             // try-catch para incluir el archivo
  11.             // Verifico que exista la clase
  12.             $this->_models[$model] = new $class();
  13.         }
  14.         return $this->models[$model];
  15.     }
  16.     // Crear archivo de cache
  17.     public function saveCache($file, $contents) {
  18.         // Guardo todo en un archivo
  19.     }
  20.     // Manejo de errores
  21.     public function error($msg) {
  22.         die($msg); // Es solo un ejemplo
  23.     }
  24. }
  25.  
  26. // Clase base para tener acceso a funciones generales en modelo, vista y controlador
  27. class base {
  28.     protected function __construct() {}
  29.     public function error($msg) {
  30.         global $principal;
  31.         $principal->error($msg);
  32.     }
  33. }
  34.  
  35. // Clase para modelos
  36. class myModel extends base {
  37.     protected function __construct() {}
  38.     public function saveCache($file, $contents) {
  39.         global $principal;
  40.         $principal->saveCache($file, $contents);
  41.     }
  42. }
  43.  
  44. // Modelo para configuracion del sistema
  45. class configModel extends myModel {
  46.     private $_config = array(); // Acceso y modificacion con getter y setter
  47.     public function __construct() {
  48.         // Cargo la configuracion desde la base de datos
  49.         // Si algo falla:
  50.         parent::error('No se puede cargar la configuracion.');
  51.     }
  52.     public function saveConfig($newValues) {
  53.         // Guardo los nuevos valores de configuracion
  54.         // Guardo todo en archivo de cache
  55.         parent::saveCache('config', $this->_config);
  56.     }
  57. }

Ok, ese es el resumen de lo que llevo hasta ahora, por el momento tengo la clase para conexion y manejo de base de datos "por fuera" y tengo que estar usando global $db; para tener acceso a sus metodos.

Todos los comentarios y sugerencias son bienvenidos. Gracias.
__________________
- León, Guanajuato
- GV-Foto
  #2 (permalink)  
Antiguo 03/04/2011, 03:23
Avatar de Triby
Mod on free time
 
Fecha de Ingreso: agosto-2008
Ubicación: $MX->Gto['León'];
Mensajes: 10.106
Antigüedad: 15 años, 8 meses
Puntos: 2237
Respuesta: Solicitud de orientacion

Despues de iniciar el tema tuve la duda de si usar parent::funcion(); para ejecutar los metodos heredados era correcto o debia usar self::funcion(); o, incluso $this->funcion(); y, probando me di cuenta que las 3 formas funcionan.

La pregunta es: Cual de las 3 opciones es la mas apropiada?

Nota: No edite el inico del tema porque me parecio que la pregunta es importante como para estar en otro mensaje, pero no en un tema aparte.
__________________
- León, Guanajuato
- GV-Foto
  #3 (permalink)  
Antiguo 03/04/2011, 06:19
Avatar de masterpuppet
Software Craftsman
 
Fecha de Ingreso: enero-2008
Ubicación: Montevideo, Uruguay
Mensajes: 3.550
Antigüedad: 16 años, 3 meses
Puntos: 845
Respuesta: Solicitud de orientacion

Que tal Triby,

a ver:

1 - los modelos no deberian redireccionar, en todo caso lanzar una excepción o guardar el error y que el controller compruebe el estado para decidir que hacer.

2 - global state, mala palabra, yo lo trataría de evitar, podrías refactorizar a algo así:

Código PHP:
Ver original
  1. class Base
  2. {
  3.     protected $_principal;
  4.  
  5.     public function __construct(Principal $p)
  6.     {
  7.         $this->_principal = $p;
  8.     }
  9.  
  10.     public function error($msg)
  11.     {
  12.         $this->_principal->error($msg);
  13.     }
  14. }

y si no queres estar pasando Principal en cada una de las clases, podes hacer un fallback a registry, claro tendrias que tener registry :), pero es algo simple de construir ,

Código PHP:
Ver original
  1. public function __construct(Principal $p = null)
  2. {
  3.    if(null === $p) {
  4.         $p = $this->_getDefaultPrincipal();
  5.     }
  6.    $this->_principal = $p;  
  7. }
  8.  
  9. protected function _getDefaultPrincipal()
  10. {
  11.     if(!Registry::has('principal')) {
  12.         throw new ModelException(/**/);
  13.     }
  14.     return Registry::get('principal');
  15. }

Aclaración: esto también oculta dependencias, lo ideal seria utilizar DI.

3 - no entiendo bien, queres hacer una clase base(Object) para todos, modelos, vista y controladores ?

4 - Si cada uno debería tener su clase base especifica.

Con respecto a parent, this y self:
  1. parent hace referencia a la clase base
  2. this hace referencia a la instancia actual
  3. self hace referencia a la clase actual

PHP lo maneja de una forma particular, pero deberías utilizar self para acceder a los miembros estáticos, en tu ejemplo yo utilizaria $this->saveCache, $this->error y parent lo utilizaría, si por ejemplo reescribiera saveCache en configModel,
Código PHP:
Ver original
  1. class ConfigModel extends Base
  2. {
  3.     private $_config = array();
  4.  
  5.     public function __construct()
  6.     {
  7.         // Cargo la configuracion desde la base de datos
  8.         // Si algo falla:
  9.         $this->error('No se puede cargar la configuracion.');
  10.     }
  11.  
  12.     public static function log($message)
  13.     {...}
  14.  
  15.     public function saveConfig($newValues)
  16.     {
  17.         // Guardo los nuevos valores de configuracion
  18.         // Guardo todo en archivo de cache
  19.         $this->saveCache('config', $this->_config);
  20.         self::log('cache saved  ' .  time());
  21.     }
  22.  
  23.    public function saveCache($file, $contents, $save = false)
  24.    {
  25.        if(true === $save) {
  26.           parent::saveCache($file, $contents);
  27.        }
  28.       ...
  29.    }
  30.  
  31. }

Saludos.
__________________
http://es.phptherightway.com/
thats us riders :)

Última edición por masterpuppet; 03/04/2011 a las 07:36 Razón: aclaración
  #4 (permalink)  
Antiguo 03/04/2011, 08:41
Avatar de abimaelrc
Colaborador
 
Fecha de Ingreso: mayo-2009
Ubicación: En el planeta de Puerto Rico
Mensajes: 14.734
Antigüedad: 15 años
Puntos: 1517
Respuesta: Solicitud de orientacion

Una duda, ¿php no tiene una clase llamada Registry? (¿o me equivoco?). Si es así, que php no tiene una clase llamada Registry, pues como lógica tendría que crearla. Si es así, ?qué métodos recomiendas que se usen en un registry aparte de set, get y has?

Edito: Esto encontré por internet, pero no sé si es correcto, claro está no cumple con todas las recomendaciones que sugiere zend, de estandarizar el código, pero aparte de eso, ¿es todo lo que necesita o faltaría algo?
__________________
Verifica antes de preguntar.
Los verdaderos amigos se hieren con la verdad, para no perderlos con la mentira. - Eugenio Maria de Hostos
  #5 (permalink)  
Antiguo 03/04/2011, 08:46
Avatar de carlos_belisario
Colaborador
 
Fecha de Ingreso: abril-2010
Ubicación: Venezuela Maracay Aragua
Mensajes: 3.156
Antigüedad: 14 años
Puntos: 461
Respuesta: Solicitud de orientacion

hasta donde tengo entendido con varias lecturas no pero aca http://desarrolladorsenior.blogspot....ry-en-php.html tienes una implementación que pudieras utilizar. saludos
__________________
aprende d tus errores e incrementa tu conocimientos
it's not a bug, it's an undocumented feature By @David
php the right way
  #6 (permalink)  
Antiguo 03/04/2011, 09:53
Avatar de masterpuppet
Software Craftsman
 
Fecha de Ingreso: enero-2008
Ubicación: Montevideo, Uruguay
Mensajes: 3.550
Antigüedad: 16 años, 3 meses
Puntos: 845
Respuesta: Solicitud de orientacion

Cita:
Iniciado por abimaelrc Ver Mensaje
Una duda, ¿php no tiene una clase llamada Registry? (¿o me equivoco?). Si es así, que php no tiene una clase llamada Registry, pues como lógica tendría que crearla. Si es así, ?qué métodos recomiendas que se usen en un registry aparte de set, get y has?
PHP no tiene clase Registry pero se puede utilizar como contenedor ArrayObject(Zend_Registry extiende de esta clase), para mi la clase debería tener los métodos básicos get, set, has, remove e implementar Iterator y Countable.

Cita:
Iniciado por abimaelrc Ver Mensaje
Esto encontré por internet, pero no sé si es correcto, claro está no cumple con todas las recomendaciones que sugiere zend, de estandarizar el código, pero aparte de eso, ¿es todo lo que necesita o faltaría algo?
No es un Registry "puro" , es Lazy Registry(según su autor), si no te interesa esa característica, seria demasiado.

@carlos la clase que propones tiene una particularidad, se pueden crear varias instancias y todas comparten el mismo contenedor de datos, así lo hace Zend_Registry

Saludos.
__________________
http://es.phptherightway.com/
thats us riders :)
  #7 (permalink)  
Antiguo 03/04/2011, 11:38
Avatar de Triby
Mod on free time
 
Fecha de Ingreso: agosto-2008
Ubicación: $MX->Gto['León'];
Mensajes: 10.106
Antigüedad: 15 años, 8 meses
Puntos: 2237
Respuesta: Solicitud de orientacion

Primero que nada, gracias a los tres por sus valiosos aportes, al parecer no estoy tan equivocado en la forma en que tengo planeado hacer esto.

masterpuppet, de acuerdo, en el modelo solamente tendria funciones de acceso a base de datos y las redirecciones deberian ser especificamente en el controlador; tengo cambiar mis habitos y aclararme un poco sobre los metodos que deben aparecer en cada objeto.

Sobre lo del registro y mis dudas entre parent:: self:: y $this->, parece que anoche al publicar el tema ya estaba medio dormido, pero hoy al levantarme me "cayo el veinte"

Al parecer, ya estoy haciendo algo similar al patron singleton + registry para los modulos cargados al tener $principal->_models y $principal->getModel()... aunque claro, necesito revisar las sugerencias para pulir y adaptar esta parte de acuerdo a sus sugerencias.

Mi confusion entre global, parent::, self:: y $this-> fue porque anoche ya estaba medio dormido, pero ahora lo tengo mas claro:

Definitivamente quiero evitar el uso de global, pero en mis primeras pruebas no funcionaba ninguna de las resoluciones de ambito, pero... era poque en principal->__construct() intentaba crear otros objetos y, obviamente, no se creaba el mismo $principal, primero tiene que salir del constructor.

Para cuando resolvi esto, en las clases base ya habia creado los metodos para tener acceso a la principal y despues fue cuando probe parent::, self:: y $this->

Porque me funcionan las 3 formas?
1- Al instanciar el modulo en $principal->_models (con el metodo $principal->getModel()) ya tengo acceso por medio de parent:: y creo que asi es como debo usarlo.
2- Lo que hace que tambien funcionen self:: y $this-> son los metodos heredados de las clases base y no son necesarios ahi.

Ahora, solo tengo que ver cuales metodos debo permitir que queden accesibles a otros objetos por medio de parent:: y cuales no.

Tambien, el objeto de acceso a base de datos lo voy a "mudar" a $principal->db.

masterpuppet, Abimael y carlos_belisario, nuevamente muchas gracias, es muy util la informacion proporcionada.
__________________
- León, Guanajuato
- GV-Foto
  #8 (permalink)  
Antiguo 04/04/2011, 22:37
Avatar de Triby
Mod on free time
 
Fecha de Ingreso: agosto-2008
Ubicación: $MX->Gto['León'];
Mensajes: 10.106
Antigüedad: 15 años, 8 meses
Puntos: 2237
Respuesta: Solicitud de orientacion

He estado entretenido con un poco (mucho) de lectura acerca de objetos y ahora si ya me aclare un poco mas y me retracto de las burradas que dije en el mensaje anterior:

$this-> para tener acceso a propiedades y metodos dentro del mismo objeto.
self:: para tener acceso a propiedades (?) y metodos declarados en la clase con la cual se instancio el objeto.
parent:: para tener acceso a la clase padre, de donde se extiende la actual (que dije? )

Bien, entonces, si usaba parent:: tenia acceso a los metodos por extender la clase desde base, si usaba self: tenia acceso por extender desde model, view o controler y, su usaba $self-> tenia acceso porque el metodo se hereda.

Todo esto me llevo a reecribir nuevamente todo lo que llevaba, al menos las bases de donde voy a extender para determinar el "esqueleto" de cada tipo de objeto que vaya a necesitar, aun no se como sera, pero ya llegare a ese punto.

Ahora, lo que estoy haciendo es tomar la idea de CodeIgniter para crear un "super objeto" y evitando, en la medida de lo posible, hacer recursiones aunque realmente no consume mucha memoria (segun mis pruebas, entre 150 y 200 bytes por cada objeto que incluye una propiedad que hace referencia al super objeto).

Hay muchos conceptos que aun no entiendo y logica que todavia no tengo NPI (ni la mas remota idea) de como aplicarla, pero supongo que conforme vaya avanzando y viendo como estan programados algunos frameworks y CMS ire solventandolos.

P.D. Hasta ahora solo llevo un global $variable porque incluyo un archivo desde un objeto para instanciar otro... es un problema de logica, pero como es un caso especial y fuera de cualquier objeto, lo dejare para resolverlo despues.
__________________
- León, Guanajuato
- GV-Foto
  #9 (permalink)  
Antiguo 05/04/2011, 03:40
Avatar de masterpuppet
Software Craftsman
 
Fecha de Ingreso: enero-2008
Ubicación: Montevideo, Uruguay
Mensajes: 3.550
Antigüedad: 16 años, 3 meses
Puntos: 845
Respuesta: Solicitud de orientacion

Que tal Triby,

$this y parent funcionan como se espera, el que tiene un comportamiento "extraño" es self.

self no hace referencia a la clase donde se instancio el objeto, hace referencia a la clase donde se definió, (lo que conlleva a que el polimorfismo en contexto estático no sirva de nada), para solucionar esto PHP 5.3 introduce lo que se conoce como late static binding.

Con respecto al "súper objeto"(es un layer supertype con esteroides :) ?), que razón hay para que esto sea así ?, que tienen en común una vista, modelo y controller ?, entiendo que debe ser para aprovechar la "magia" de php y definir setters, getters y talvés setOptions ?, aunque la tendencia actual es cada vez menos magia y mas explicito(esto para mi es mejor).

Otra cosa, tomar CI como ejemplo no creo que sea lo más adecuado, a mi entender tiene un poco torcida la definición de hacer las cosas bien, y demasiados wtfs/m(medida estándar de calidad de código :) ), la referencia podria ser Zend, Symfony, Yii.

Por último y no te doy mas lata, deberías hacer como si global no existiera, utiliza en su lugar alguna implementación de registry + singleton.

Saludos.
__________________
http://es.phptherightway.com/
thats us riders :)

Última edición por masterpuppet; 05/04/2011 a las 03:55
  #10 (permalink)  
Antiguo 05/04/2011, 09:13
Avatar de Carxl
Colaborador
 
Fecha de Ingreso: agosto-2006
Ubicación: Bogotá
Mensajes: 2.993
Antigüedad: 17 años, 9 meses
Puntos: 70
Respuesta: Solicitud de orientacion

Me parece muy bueno @Triby que te intereses por este tema, yo ahora intento aprender patrones, porque ando algo flojo en ellos.

Quiero aprender al menos los más usados, mvc (sin framework), object, observer y saber como usarlos.

En cuanto a lo que dice @masterpuppet de CodeIgniter, lastimosamente (uso Codeigniter) tiene razón, alguna vez me dió por ver su lógica, y no fue la mejor impresión.

Ahora ando viendo Yii, Symfony nunca me gustó. Y Zend, Zend es el papá xD

Bien por ti
__________________
Hay 10 tipos de personas, los que entienden binario y los que no. (Anónimo)
www.programandoweb.com
  #11 (permalink)  
Antiguo 05/04/2011, 15:58
Avatar de Triby
Mod on free time
 
Fecha de Ingreso: agosto-2008
Ubicación: $MX->Gto['León'];
Mensajes: 10.106
Antigüedad: 15 años, 8 meses
Puntos: 2237
Respuesta: Solicitud de orientacion

masterpuppet, no quiero extender todas las clases en base a una sola, que fue mi loca idea original, solo quiero tener una que se encargue de crear todos los objetos y conserve el acceso a ellos, por referencia y, si comparten propiedades o metodos, sera de acuerdo a las necesidades y no por herencia.

Lo del global: en config.php tengo info para conectar a base de datos, tipo, host, usuario, etc. y tengo un archivo db.php que debe verificar el tipo para poder incluir el archivo con la clase correcta, pero como proviene de una funcion donde dbHost no esta visible, opte por "global" en lugar de definir una constante que se requiere una sola vez.

Carxl, cierto, he visto cosas de CodeIgniter que no me gustan, incluso en la codificacion (aunque yo todavia no sigo un estandar en estas cuestiones). Voy a echarle un vistazo a Zend (alguna vez lo vi), a Yii (no lo conozco) y a Symfony (no recuerdo si ya lo revise).

Gracias a ambos por los buenos aportes.

Edito: Por el momento solo revisare Yii y esperare mas noticias de la nueva version para probarlo:

Cita:
Iniciado por Yii Framework
While Yii 1.1.x is working extremely well, we do not want to stop here.

Our next major release Yii 2.0 will be a complete rewrite of the framework on top of PHP 5.3.0+. It will not be fully compatible with 1.1.x. However, we will try every effort to make the transition as easy as possible.
Re-edito:
Zend es un monstruoso ZIP de 25mb, ya decia yo que algo me habia mantenido alejado de el... pero bueno, todo sea por ver "sus tripas", saber como trabaja y aprender algo nuevo.
__________________
- León, Guanajuato
- GV-Foto

Última edición por Triby; 05/04/2011 a las 16:08
  #12 (permalink)  
Antiguo 05/04/2011, 19:46
Avatar de carlos_belisario
Colaborador
 
Fecha de Ingreso: abril-2010
Ubicación: Venezuela Maracay Aragua
Mensajes: 3.156
Antigüedad: 14 años
Puntos: 461
Respuesta: Solicitud de orientacion

Interesantisimo post este de verdad, aunque mi experiencia es poca antes de la de los amigos que tienen este gran debate voy a ver si me puedo meter y aportar un poco en el tema ,


Cita:
masterpuppet, no quiero extender todas las clases en base a una sola, que fue mi loca idea original, solo quiero tener una que se encargue de crear todos los objetos y conserve el acceso a ellos
No se si estoy en lo cierto o entendi bien pero creo que la solucion a esto seria que implementaras un factory, cuya razon de existencia es esa crear objetos el articulo de wikipedia creo que tiene un link a un ejemplo con PHP, en cuanto a lo de clases principales, creo que para la implementación del MVC tendrias que tener por algunas para extender por lo menos un model,controller y un view aunque yo personalmente no me he metido tan alla en este patron con ayuda de lecturas y tutoriales mas o menos he creado algunas clases base de estas y hasta ahora me ha parecido que voy mejorando en mis desarrollos aunque me falte bastante, la idea de la que hablas de una superclase creo que no eres el primero que se le ocurre a mi también se me habia ocurrido esa idea cuando comence a meterme con OOP hasta que me hicieron pisar piso y ponerme a investigar sobre algo que se llama responsabilidad unica (separacion de responsabilidades) desde ahi me siento a ver que tiene que hacer en especifico cada objeto que voy a crear, espero que le sea de ayuda lo que le indique saludos
__________________
aprende d tus errores e incrementa tu conocimientos
it's not a bug, it's an undocumented feature By @David
php the right way
  #13 (permalink)  
Antiguo 05/04/2011, 21:15
Avatar de Triby
Mod on free time
 
Fecha de Ingreso: agosto-2008
Ubicación: $MX->Gto['León'];
Mensajes: 10.106
Antigüedad: 15 años, 8 meses
Puntos: 2237
Respuesta: Solicitud de orientacion

Cita:
Iniciado por carlos_belisario
No se si estoy en lo cierto o entendi bien...
carlos_belisario, entendiste mas o menos bien ... explico:

Originalmente estaba haciendo la burrada de extender todo desde una misma clase base.

Siguiendo las sugerencias de masterpuppet, reescribi lo que llevaba para dejar el "nucleo" como responsable de administrar cualquier objeto creado, pero sin heredar cosas que no debe; ya estoy viendo lo del metodo Factory y tambien algo sobre Namespace para considerar otras alternativas.

Aparte de esto, las clases abstractas para modelo, vista y controlador, por ahora no tienen propiedades o metodos, hasta que defina que voy a hacer y planear como lograrlo y si, definitivamente, habra un "padre" para cada uno de ellos.

Cita:
Iniciado por carlos_belisario
Interesantisimo post este de verdad, aunque mi experiencia es poca antes de la de los amigos que tienen este gran debate voy a ver si me puedo meter y aportar un poco en el tema
Claro que el aporte es muy util, tanto la informacion como los puntos de vista son muy interesantes, gracias!
__________________
- León, Guanajuato
- GV-Foto

Etiquetas: $this->, parent::, self::
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

SíEste tema le ha gustado a 3 personas




La zona horaria es GMT -6. Ahora son las 23:42.