Existen funciones de PHP que nos permiten mandar a llamar una función o un método dentro de una clase, sin conocer el nombre de éstas o los parámetros que le vayamos a pasar,  como: call_user_func o call_user_func_array.

Sin embargo, ¿cómo creamos o instanciamos un objeto cuando no sabemos ni el nombre ni el número de parámetros? Pongámoslo más sencillo, supongamos que tenemos la siguiente clase:

<?php
class Prueba
{
    public function suma($param1, $param2)
    {
        return $param1 + $param2;
    }
}
?>

Con lo que conocemos podríamos hacerlo de la siguiente forma:

<?php
    $params = array(5, 3);
    $result = call_user_func_array(array('Prueba', 'suma'), $params);
    echo "La suma de {$params[0]} + {$params[1]} es igual a {$result}";        //Salida: La suma de 5 + 3 es igual a 8
?>

De ese modo podríamos tener una clase con un método al que le podemos pasar cuantos parámetros sean requeridos, pero esto no resuelve mi problema, dado que primero necesitamos saber el nombre de la calse y del método y, por supuesto, el número de parametros.

A donde se quiere llegar es a crear sólo el objeto, sin llamar a algun método, tal vez podría solucionarse utlizando ‘__construct’, en la parte de la funcion donde indicamos el método a invocar, pero que hay de los parámetros, aun necesito saber cuantos son requeridos, necesito algo parecido a esto:

    call_user_func_array('ClassName', array($param1, $param2, $param3, ..., $paramN));

Para ésto existe la serie de clases Reflection de PHP, que nos permite hacer ingeniería de reversa en clases, interfaces, funciones, métodos y extensiones.

<?php
function create_user_class_array($className, $params = array())
{
    $reflection = new ReflectionClass($className);
    return $reflection->newInstanceArgs($params);
}

class Test
{
    public $output;

    public function __construct()
    {
        $this->output = "Este objeto no tiene parametros";
    }
}

class Test2
{
    public function __construct($param1, $param2)
    {
        echo "Este objeto tiene 2 parametros: {$param1} y {$param2}";
    }
}

class Test3
{
    protected $params;
    public function __construct($param1, $param2, $param3)
    {
        $this->params = array($param1, $param2, $param3);
    }

    public function showParams()
    {
        echo "Este objeto tiene 3 parametros: {$this->params[0]}, {$this->params[1]} y {$this->params[2]}";
    }
}

//Test 1
$test = create_user_class_array('Test');
echo $test->output;   //Salida: Este objeto no tiene parametros

$test2 = create_user_class_array('Test2', array('uno', 'dos'));      //Salida: Este objeto tiene 2 parametros: uno y dos

$test3 = create_user_class_array('Test3', array('uno', 'dos', 'tres'));
$test3->showParams();         //Salida: Este objeto tiene 3 parametros: uno, dos y tres

Y listo, problema resuelto, al llamar a la funcion create_user_class_array() me instancia el objeto haciendo uso del Reflection y no dependo de saber los parametros, ¿cómo o dónde lo ocupo?, que tal si tenemos un método mágico __call, por ejemplo:

<?php
class MyTest
{
    public function __call($className, array $params)
    {
        //Si el código fuera como el de siguiente,
        //return new $className($params);
        //marcaria error porque la clase $className puede requerir más de un parámetro y no necesariamente array
        //utilizaremos lo siguiente:

        $reflection = new ReflectionClass($className);
        return $reflection->newInstanceArgs($params);
    }
}

$obj = new MyTest;
echo $obj->Test1()->output;
$obj->Test2('uno', 'dos');
$obj->Test3('uno', 'dos', 'tres')->showParams();
$obj->AnyClass('my param', 1, 3.5, array('x', 'y'));

Ahora podemos crear objetos on-the-fly.

Hace algunos días estaba tratando de ponerle algo de diseño a los formularios mediante CSS, lo que intentaba hacer es que al poner el foco sobre alguno de los campos, éste cambiara de apariencia (el borde, el color, etc.), es decir, cuando el cursor estuviera situado en algún campo.

Se me hizo muy fácil hacer lo siguiente:

<form action="#" method="post">
<label for="nombre">Nombre:</label>
<input name="nombre" type="text" />
<label for="email">Email:</label>
<input name="email" type="text" />
<input type="submit" value="enviar" />
</form>

y el CSS quedaría así:

input[type="text"]  {
 border: 1px solid #dadada;
 background-color: #efefef;
}

input[type="text"]:focus {
 border: 1px solid #333;
 background-color: #fff;
}

Para la mayoría de los navegadores funcionó el efecto que quería, pero al probarlo con el maldito IExplorer, como de costumbre no funcionó porque éste no soporta algunas pseudo-clases, en este caso :focus, entonces tuve que hacer un pequeño truco utilizando los eventos onfocus y onblur de javascript y modificar un poco el código HTML quedando así:

<form action="#" method="post">
<label for="nombre">Nombre:</label>
<input name="nombre" type="text" onfocus="this.className='focus'" onblur="this.className=''" />
<label for="email">Email:</label>
<input name="email" type="text" onfocus="this.className='focus'" onblur="this.className=''" />
<input type="button" value="enviar" />
</form>

y el CSS queda así:

input[type="text"]  {
 border: 1px solid #dadada;
 background-color: #efefef;
}
input[type="text"].focus {
 border: 1px solid #333;
 background-color: #fff;
}

Nótese que el único cambio en el CSS es el de un punto(.) en lugar de dos puntos(:), esto es porque ahora en lugar de utilizar la pseudo-clase :focus, hemos creado la clase focus.

Ahora podemos comprobar que efectivamente el efecto funciona para cualquier navegador incluyendo el IExplorer.

Mientras me encuentro realizando la interfaz para el nuevo proyecto que tengo en el tintero, surgió el problema de cómo crear contenedores con las esquinas redondeadas, en un principio, investigando en google vi que se podía mediante una librería de javascript llamada Nifty Corners Cube, si bien es sencillo su uso, no es muy flexible y hay que agregar un llamado a la función de javascript por cada elemento que requiera esquinas redondeadas, aunque se pueden definir por las clases del tag de html, no se me hizo la mejor opción, por lo que decidí hacerlo con CSS.

Lo que se tiene que hacer primero es crear la estructura de los divs, para crear esto, el código HTML será algo como esto:

<div id="box">
 <div id="top">
 <div class="corner_left"></div>
 <div class="center"></div>
 <div class="corner_right"></div>
 </div>
 <div class="content">Aquí va el contenido!</div>
 <div id="bottom">
 <div class="corner_left"></div>
 <div class="center"></div>
 <div class="corner_right"></div>
 </div>
 </div>

ahora lo siguiente es crear una imagen que nos dará las esquinas redondeadas. mi imagen, en este caso la esquina tiene una redondez de 6 pixeles, por lo tanto haremos una imagen de 12 x 12px

Medidas de la imagen

Medidas de la imagen

Nota: La imagen está amplificada a 800%.

En realidad debe de quedar una imagen como la siguiente…

Imagen Final

A continuación, utilizando una técnica llamada sprites, la cual consiste en posicionar correctamente los backgrounds de la imágenes y un poco de CSS para ordenar los divs tendremos una caja contenedora con esquinas redondeadas, a continuación el CSS

#box {
        margin: 0 auto;
        width:200px;
    }
    .corner_left, .corner_right {
        height:6px;
        width:6px;
    }
    .center {
        height:5px;
        width:188px;
        float:left;
    }
    #top .corner_left{
        background:url(images/rounded_corner.png) no-repeat top left;
        float:left;
    }
    #top .center {
        border-top:1px solid #d80000;
    }
    #top .corner_right{
        background:url(images/rounded_corner.png) no-repeat top right;
        float:right;
    }
    #bottom .corner_left{
        background:url(images/rounded_corner.png) no-repeat bottom left;
        float:left;
    }
    #bottom .center {
        border-bottom:1px solid #d80000;
    }
    #bottom .corner_right{
        background:url(images/rounded_corner.png) no-repeat bottom right;
        float:right;
    }
    .content {
        font-family:Arial, Helvetica, Verdana;
        width:198px;
        height:30px;
        text-align:center;
        float:left;
        border-left:1px solid #d80000;
        border-right:1px solid #d80000;
        padding:20px 0;
    }

Puedes probar, creando imágenes de diferentes tamaños y colores, para obtener otros resultados, por cierto, los tamaños de
.center, varían dependiendo del tamaño de la imagen, para este ejemplo donde la redondez de la imagen, o sea la mitad es de 6px el valor de la altura de .center es de 5px porque se le agrega 1 px de borde en la parte superior haciendo los 6 px, lo mismo para los anchos.

Aquí esta el ejemplo terminado

Despues de bastante tiempo sin actividad le he lavado un poco la cara a este sitio y prometo que procuraré postear más seguido. Así que iniciamos nueva temporada con este sitio y con ello un nuevo proyecto que lleva como unos 9 meses en la incubadora, estoy hablando de “rentorento.com” que por falta de tiempo lo había dejado de lado pero hoy desempolvaré esos archivos que estan guardados en alguna parte de mi disco duro.

Les comento un poco sobre este proyecto, se trata de un buscador de inmuebles, que en un principio se planea funcione exclusivamente para México. Los usuarios potenciales de este buscador son las personas que esten buscando casas, departamentos, cuartos, terrenos, oficinas, etc. que se encuentren en renta o venta. Se puede buscar por categoría, tag, ciudad, etc. lo común de cualquier otro buscador, sin embargo rentorento.com tendrá la ventaja de mostrar en un mapa todas las propiedades publicadas, espero tener éxito con este proyecto que durante el proceso de desarrollo les ire comentado de su avance.