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

Extender objetos

Estas en el tema de Extender objetos en el foro de Frameworks y PHP orientado a objetos en Foros del Web. Cita: La función array_key_exists del método SetExtension no tiene segundo argumento, el segundo argumento debe ser $this->extensions_references Esto no acabé de entenderlo ... sims Si ...

  #31 (permalink)  
Antiguo 31/03/2005, 15:04
O_O
 
Fecha de Ingreso: enero-2002
Ubicación: Santiago - Chile
Mensajes: 34.417
Antigüedad: 23 años
Puntos: 129
Cita:
La función array_key_exists del método SetExtension no tiene segundo argumento, el segundo argumento debe ser $this->extensions_references
Esto no acabé de entenderlo ... sims

Si no es mucha molestia y si puedes (o quien pueda) sism82, ¿podrías poner un ejemplo de uso completo?.

Un saludo,
  #32 (permalink)  
Antiguo 31/03/2005, 15:19
Avatar de jpinedo
Colaborador
 
Fecha de Ingreso: septiembre-2003
Ubicación: Lima, Perú
Mensajes: 3.120
Antigüedad: 21 años, 3 meses
Puntos: 41
O sea que el método setExtension debe quedar:
Código PHP:
    function SetExtension($ExtensionName
    { 
        
$ExtensionName = (string)$ExtensionName
        if ( 
array_key_exists($ExtensionName$this->extensions_references) ) // Aquí estuvo el cambio
        

            
$this->extension =& $this->extensions_references[$ExtensionName]; 
            return 
true
        } 
        { 
            die(
"Extension '{$ExtensionName}' does not has been loaded yet!"); 
        } 
         
    } 
Saludos
  #33 (permalink)  
Antiguo 31/03/2005, 15:51
Avatar de jpinedo
Colaborador
 
Fecha de Ingreso: septiembre-2003
Ubicación: Lima, Perú
Mensajes: 3.120
Antigüedad: 21 años, 3 meses
Puntos: 41
Según se ve en el constructor de FpdfExtensionsHandler.... la clase FPDF tiene que estar disponible (include?) antes de instanciar FpdfExtensionsHandler.
Mis dudas:
¿Para qué instanciamos un Fpdf automáticamente en un atributo aparte y no dentro del array $extensions_references?
Lo que veo que que no sé cómo podríamos acceder a los métodos originales que implemente FPDF.
Además me late que al hacer $this->fpdf_vars = get_class_vars('FPDF'); no estamos referenciando las variables del objeto $this->fpdf (dado a que este se crea después y no se hace un MergeExtensionVars()).

Saludos
  #34 (permalink)  
Antiguo 31/03/2005, 16:44
Avatar de sism82  
Fecha de Ingreso: octubre-2003
Ubicación: Guadalajara
Mensajes: 865
Antigüedad: 21 años, 3 meses
Puntos: 1
josemi, espero estar en lo correcto al intentar aclarar tus dudas.

1. Fpdf se instancia autoaticamente en un atributo a parte por claridad (desde mi punto de vista), debido a que no es una extensión, por lo que no vi correcto ponerlo dentro de extensions_references.
2. Los métodos originales se acceden desde $fpdf_exten_handler->fpdf->metodoOriginal();
3. Las extensiones son las que hacen referencia a fpdf y no al revés. Por eso MergeExtensionsVars se hace unicamente cuando se carga una extensión. Este metodo compara las variables de las extensiones contra las variables de la clase padre FPDF, si coinciden, entonces hace una referencia hacia la variable de FPDF. Es decir, la variable de la extensión hace referencia a la variable de la clase original FPDF.

Mas dudas? estoy diciendo puras sandeces?

saludos
  #35 (permalink)  
Antiguo 31/03/2005, 17:23
Avatar de jpinedo
Colaborador
 
Fecha de Ingreso: septiembre-2003
Ubicación: Lima, Perú
Mensajes: 3.120
Antigüedad: 21 años, 3 meses
Puntos: 41
Bastante más claro... gracias.
¿Ves todo lo que nos ahorraríamos con un simple ejemplo de uso?
Saludos
  #36 (permalink)  
Antiguo 31/03/2005, 18:45
Avatar de jpinedo
Colaborador
 
Fecha de Ingreso: septiembre-2003
Ubicación: Lima, Perú
Mensajes: 3.120
Antigüedad: 21 años, 3 meses
Puntos: 41
He estado probando y por ahora no logro que funcione.
Más bien sigue separando los objetos.
Código PHP:
require_once('fpdf.php');
require_once(
'fpdfExtensionsHandler.php');

$pdf = new FpdfExtensionsHandler();
$pdf->LoadExtension('PDF_Javascript''fpdf_js.php');
$pdf->fpdf->AddPage();
$pdf->fpdf->SetFont('Arial','B',16);
$pdf->SetExtension('PDF_Javascript');
$pdf->extension->SetFont('Arial','B',12);
echo 
'Tamaño fpdf::'.$pdf->fpdf->FontSizePt."<br />";
echo 
'Tamaño extensión::'.$pdf->extension->FontSizePt."<br />";
die(); 
Me imprime
Código:
Tamaño fpdf::16
Tamaño extensión::12
Voy a seguir viendo qué puede estar mal. (De hecho tiene que ver con las referencias)
Saludos
  #37 (permalink)  
Antiguo 31/03/2005, 19:39
Avatar de jpinedo
Colaborador
 
Fecha de Ingreso: septiembre-2003
Ubicación: Lima, Perú
Mensajes: 3.120
Antigüedad: 21 años, 3 meses
Puntos: 41
Ahora funciona... No sé era exactamente lo que estaba mal... pero me pareció más "económico" pasarle el $ExtensionName al método MergeExtensionsVars() para que de esa manera no tenga que recorrer todo el array $this->extensions_vars.
Hice el cambio y ahora sí funcionan las referencias (Ojo... funciona el ejemplo que puse anteriormente... aún no he generado un PDF.).
Aquí dejo el código de fpdfExtensionsHandler:Además he corregido los pequeños errores que reportó Cluster y alguno que otro que por ahí había.
Código PHP:
require_once('fpdf.php');
/** 
* This class has as goal, allow to use different FPDF extensions. Its created to work under PHP4 
*/ 
class FpdfExtensionsHandler 


    
/** 
     * FPDF main object 
     * @var object class FPDF 
     * @final 
     * @access public 
     */ 
    
var $fpdf                  null
     
    
/** 
     * save the variables of the FPDF class 
     * @var Array 
     * @final 
     * @access private 
     */ 
    
var $fpdf_vars             = array(); 
     
    
/** 
     * save references to the loaded extensions 
     * @var Array 
     * @final 
     * @access private 
     */ 
    
var $extensions_references = array(); 
     
    
/** 
     * save the extensions vars 
     * @var Array 
     * @final 
     * @access private 
     */ 
    
var $extensions_vars       = array(); 

    
/** 
     * current FPDF extension 
     * @var Object 
     * @final 
     * @access private 
     */ 
    
var $extension               null

     
    
/** 
     * default directory to search the extensions 
     * @var String 
     * @final 
     * @accesss private 
     */ 
    
var $default_extensions_dir './'
     
    
/** 
     * here can pass as many arguments as needed for the Fpdf constructor 
     * @return bool 
     * @param Mixed $FpdfConstructorArugment1 
     * @param Mixed $FpdfConstructorArugment2 
     * @param Mixed $FpdfConstructorArugmentN... 
     * @final 
     * @access public 
     */ 
    
function FpdfExtensionsHandler() 
    { 
        if ( 
class_exists('FPDF') ) 
        { 
            
//getting FPDF vars 
            
$this->fpdf_vars get_class_vars('FPDF'); 
             
            
//create FPDF instance 
            
$arguments        func_get_args(); 
            
$string_arguments ""
            foreach ( 
$arguments as $index => $argument 
            { 
                
$string_arguments .= "\$arguments[$index], "
            } 
            
$string_arguments substr($string_arguments,0,strlen($string_arguments) - 2); 
            
$eval_code        "\$this->fpdf = new FPDF({$string_arguments});"
            eval(
$eval_code);
            return 
true
        } 
        else 
        { 
            die(
"Missing class FPDF!"); 
        } 
    } 
     
    
/** 
     * Try to load a new extension 
     * @return bool 
     * @param String $ExtensionName 
     * @param String $ExtensionDirectory 
     * @param Mixed $ExtensionConstructorArg1 
     * @param Mixed $ExtensionConstructorArg2 
     * @param Mixed $ExtensionConstructorArgN... 
     * @final 
     * @acces public 
     */ 
    
function LoadExtension($ExtensionName$ExtensionFile$ExtensionDirectory null
    { 
        
$ExtensionName      = (string)$ExtensionName
        
$ExtensionDirectory $ExtensionDirectory === null 
                            
null 
                            
: (string)$ExtensionDirectory
        
$class_file  $ExtensionDirectory === null 
                     
$this->default_extensions_dir.$ExtensionFile 
                     
$ExtensionDirectory.$ExtensionFile
        if ( 
file_exists($class_file) ) 
        { 
            include_once 
$class_file
            if ( !
class_exists($ExtensionName) ) 
            { 
                die(
"Class '{$ExtensionName}' does not exists in file '{$class_file}'!"); 
            } 
            else 
            { 
                
//getting extension constructor arguments 
                
$arguments   func_get_args(); 
                
$num_args    count($arguments); 
                
$string_args ""
                for ( 
$i 2$i $num_args$i++ ) 
                { 
                    
$string_args .= "\$arguments[$i], "
                } 
                
$string_args substr($string_args,0,strlen($string_args) - 2); 
                
$eval_code "\$this->extensions_references[\$ExtensionName] =& new \$ExtensionName($string_args);";
                eval(
$eval_code); 
                if ( !
is_subclass_of($this->extensions_references[$ExtensionName], 'FPDF') ) 
                { 
                    die(
"Class '{$ExtensionName}' is not a subclass of FPDF!"); 
                } 
                else 
                { 
                    
$this->extensions_vars[$ExtensionName] = array(); 
                    
$this->extensions_vars[$ExtensionName] = get_class_vars($ExtensionName); 
                    
$this->MergeExtensionsVars($ExtensionName); 
                    return 
true
                } 
            } 
        } 
        else 
        { 
            die(
"Unable to open class file '{$class_file}'!"); 
        } 
         
    } 
     
    
/** 
     * Merge the loaded extensions variables, so every instance will edit the same variables 
     * @return bool 
     * @param void 
     * @final 
     * @acces private 
     */ 
    
function MergeExtensionsVars($ExtensionName
    { 
        foreach ( 
$this->extensions_vars[$ExtensionName] as $variable_name => $variable_value 
        { 
            if ( 
array_key_exists($variable_name$this->fpdf_vars) ) 
            { 
                
$this->extensions_references[$ExtensionName]->$variable_name =& $this->fpdf->$variable_name
            } 
        } 
    } 
     
    
/** 
     * Change the default directory for extensions 
     * @return bool 
     * @param String $DirectoryName 
     * @final 
     * @acces public 
     */ 
    
function SetDefaultExtensionDir($DirectoryName
    { 
        
$this->default_extensions_dir = (string)$DirectoryName
        return 
true
    } 
     
    
/** 
     * Change the working extension 
     * @return bool 
     * @param String $ExtensionName 
     * @final 
     * @acces public 
     */ 
    
function SetExtension($ExtensionName
    { 
        
$ExtensionName = (string)$ExtensionName
        if ( 
array_key_exists($ExtensionName$this->extensions_references) ) 
        { 
            
$this->extension =& $this->extensions_references[$ExtensionName]; 
            return 
true
        } 
        { 
            die(
"Extension '{$ExtensionName}' does not has been loaded yet!"); 
        } 
         
    } 

Saludos
  #38 (permalink)  
Antiguo 31/03/2005, 19:56
Avatar de jpinedo
Colaborador
 
Fecha de Ingreso: septiembre-2003
Ubicación: Lima, Perú
Mensajes: 3.120
Antigüedad: 21 años, 3 meses
Puntos: 41
mmm...
Ahora lo probé utilizando una sola extensión y parece funcionar correctamente
Código PHP:
require_once('fpdf.php');
require_once(
'fpdfExtensionsHandler.php');

$pdf = new FpdfExtensionsHandler();
$pdf->LoadExtension('PDF_Javascript''fpdf_js.php');
$pdf->fpdf->AddPage();
$pdf->fpdf->SetFont('Arial','B',16);
$pdf->SetExtension('PDF_Javascript');
$pdf->extension->SetFont('Arial','B',18);
$pdf->fpdf->Cell(40,10,'¡PDF generado por desde fpdf!');
$pdf->extension->IncludeJS("print(true);");
$pdf->extension->Output(); 
Esto funciona. Escribe el texto (desde el padre fpdf) y envía la orden de imprimir (desde el hijo FPDF_Javascript).
Saludos
  #39 (permalink)  
Antiguo 31/03/2005, 20:06
Avatar de jpinedo
Colaborador
 
Fecha de Ingreso: septiembre-2003
Ubicación: Lima, Perú
Mensajes: 3.120
Antigüedad: 21 años, 3 meses
Puntos: 41
Si se dan cuenta el Output() lo hice desde el objeto "extension". Se supone que si lo hago desde cualquier otro objeto debería funcionar igual. Pero si en lugar de eso pongo
Código PHP:
$pdf->fpdf->Output(); 
Entonces en este caso se ignora el JavaScript y sólo se ejecuta lo que se escribió directamente en el padre.
En realidad no es que se ignore el JavaScript... lo que pasa es que esa extensión sobreescribe un par de métodos que son llamados por Output(). Estos métodos son _putresources() y _putcatalog().

En la sobreescritura se realizan los cambios necesarios para incluir JavaScript. Si los llamas desde "extension" (mientras utilizas la extensión de JavaScript, claro) se ejecutan los métodos sobreescritos y se incluye el JavaScript. Pero si los llamas desde fpdf (el padre, o desde cualquier otra extensión que no sea la de JavaScript) no se ejecutará, como es lógico, pues el método original de fpdf no tiene por qué estar enterado que ha sido reescrito por uno de sus hijos.

Hemos referenciado todos los atributos, pero no se va a poder hacer lo mismo con los métodos debido a que los atributos sí son comunes, mientras que cada extension sobreescribe los métodos a su conveniencia.

Todo funcionará bien, mientras que no haya otra extension que sobreescriba los mismos métodos... y además habría que hacer el output siempre desde la extensión de JavaScript. Pero el funcionamiento de la clase estaría demasiado condicionado y no cumpliría con lo que queríamos al comienzo. Además que es seguro que varias extensiones sobreescribirán los métodos críticos.

Conclusión: Cluster... creo que por ahora vas a tener que seguir haciendo las cosas como las haces.

Saludos

Última edición por jpinedo; 31/03/2005 a las 20:48
  #40 (permalink)  
Antiguo 31/03/2005, 22:41
Avatar de sism82  
Fecha de Ingreso: octubre-2003
Ubicación: Guadalajara
Mensajes: 865
Antigüedad: 21 años, 3 meses
Puntos: 1
jajaja..... buena conclusion he. bueno, sigo sin tiempo de checar a fondo las clases, pero parece que Josemi ya se estuvo divirtiendo un rato con las clases y llego a esa conclusion. No descarto este fin de semana darles una checada nada mas por hobby a ver si se me ocurre alguna pachecada.

Saludos!
  #41 (permalink)  
Antiguo 01/04/2005, 06:38
O_O
 
Fecha de Ingreso: enero-2002
Ubicación: Santiago - Chile
Mensajes: 34.417
Antigüedad: 23 años
Puntos: 129
Jpinedo
Cita:
Hemos referenciado todos los atributos, pero no se va a poder hacer lo mismo con los métodos debido a que los atributos sí son comunes, mientras que cada extension sobreescribe los métodos a su conveniencia.
Si, eso es cierto .. la classe que puse de ejemplo "cabecera_pie" hace eso mismo .. ree-escribe los métodos head() y footer() del FPDF padre .. Otrás classes parece que algunas también hacen lo mismo .. Por ejemplo hay algunas que re-escriben un método por completo; sólo se mantiene el nombre del objeto y la forma que devuelve su resultado .. pero hasta (por ejemplo) aportan más parámetros de entrada pues hacen algunas funcionalidades extra.

Bajo ese punto de vista y por las conclusiones que Ud's (los que saben de OOP xD) están llegando, parece que voy a tener que seguir "cortando" y pegando todo lo que necesite sobre una classe "hija" genérica según necesites .. Que tambíen por otro lado .. son algunas funcionalidades "básicas" que no sé por qué no están incluidos en el objeto "padre" (como cosas de javascript, el tema del "footer" y "header" .. etc).

Gracias por el interes!!!.

Un saludo,
  #42 (permalink)  
Antiguo 01/04/2005, 11:27
Avatar de jpinedo
Colaborador
 
Fecha de Ingreso: septiembre-2003
Ubicación: Lima, Perú
Mensajes: 3.120
Antigüedad: 21 años, 3 meses
Puntos: 41
Sólo una ligerísima aclaración:
El tal josemi ese (¿quién será?) xD... ni se ha aparecido por este post... .
Saludos
  #43 (permalink)  
Antiguo 01/04/2005, 13:23
Avatar de sism82  
Fecha de Ingreso: octubre-2003
Ubicación: Guadalajara
Mensajes: 865
Antigüedad: 21 años, 3 meses
Puntos: 1
Cita:
Iniciado por jpinedo
Sólo una ligerísima aclaración:
El tal josemi ese (¿quién será?) xD... ni se ha aparecido por este post... .
Saludos
ups, Josemi, Jpinedo, jaja ambos empiezan con ' J '. Disculpa el cambio de nombre jaja......
  #44 (permalink)  
Antiguo 17/05/2005, 18:43
Avatar de caerolus  
Fecha de Ingreso: agosto-2004
Ubicación: Madrid, España
Mensajes: 280
Antigüedad: 20 años, 4 meses
Puntos: 1
Hola. Yo sí estoy muy versado en OOP, y una solución para tu problema sería la herencia múltiple que comenta JPinedo muy bien, pero esto no está soportado en ningún lenguaje de última generación, como java, php o c#.
Una solución la ofrece el patrón de diseño Adapter. Esencialmente, el Adaptar se usa para adaptar la interface de una clase a otra interface, pero sin cambiar esta.
Por ejemplo, si queremos usar los métodos A() y B() de la interface I1, pero la clase C1 de que disponemos tiene los métodos C() y D(), hacemos esto:
Código:
class C2 extends/implements I1{
  C1 _interno;
  A(){ _interno.C(); }
  B(){ _interno.D(); }
}
De esta forma, podemos ahorrar la problemática del handler de sism8 de tener q andar cargando clases, cambiando entre unas y otras a la hora de usar lo q sea, y que realmente no tendremos un objeto especializado en algo, sino un objeto que permitirá "hacer de todo", y esto no es buena práctica en OOP.
Por ello, te aconsejo que hagas lo siguiente:
Suponiendo que tienes las clases Sub1 y Sub2 que extienden del PDF este que tienes, y quieres crear una clase Especial con métodos de Sub1 y Sub2, puedes hacer un Adapter múltiple:
Código:
 
class Especial{
  Sub1 _sub1;
  Sub2 _sub2;

  metodo1(){ _sub1.metodo1() };
  metodo2(){ _sub2.metodo2() };
  metodo3(){ _sub2.metodo3() };
  ...
  metodoN(){ _subN.metodoN() };
}
Simplemente repetir para cada método y clase que quieras utilizar/extender. Por supuesto, puedes hacer que esta clase Especial extienda de alguna de las SubX que tenemos para ahorrarte un poco de escribir, ya que las interfaces de los métodos son iguales.
Espero ser de ayuda aun. Saludo
__________________
Mi página personal: Julián Urbano
  #45 (permalink)  
Antiguo 18/05/2005, 10:38
O_O
 
Fecha de Ingreso: enero-2002
Ubicación: Santiago - Chile
Mensajes: 34.417
Antigüedad: 23 años
Puntos: 129
Ok, gracias por la sugerencia caerolus .. intentaré ponerlo en práctica si es que me aclaro.

De momento (pero no tiro la toalla) como eran pocos métodos de estas classes "auxiliares/plug-in" que necesitaba .. los "metí" a las "malas" en una classe que extiende a la "padre" .. Se que esto no es bueno, y por eso hice el planteamiento en "general" ...

Un saludo,
  #46 (permalink)  
Antiguo 15/10/2007, 14:01
 
Fecha de Ingreso: octubre-2003
Ubicación: Jalisco
Mensajes: 3
Antigüedad: 21 años, 3 meses
Puntos: 0
Re: Extender objetos

Pues si sirve de algo, su post me solucionó el problema que tenia:

Querer usar 2 extensiones para el fpdf.

Lo hice como dijo cluster "pegando dos extensiones" y rogando que no hubiera conflicto entre ellas y sus respectivos métodos.

De cualquier manera hay que buscar una solución mas ortodoxa para este detalle, estamos en contacto y no me queda mas que decir Gracias

Saludos

Última edición por rvidanar; 15/10/2007 a las 14:11
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.
Tema Cerrado




La zona horaria es GMT -6. Ahora son las 09:33.