Entradas en "php"

PHP: Ejemplo de mal lenguaje

Supongamos que tenemos 5 variables a, b, c, d y e. Y que todas y cada una de las siguientes evaluaciones devuelven TRUE.

$a === $b
$b === $c
$c === $d
$d === $e

Además si hacemos lo siguiente:

var_dump($a);
var_dump($b);
var_dump($c);
var_dump($d);
var_dump($e);

Obtenemos exactamente la misma definición, repetida 5 veces, por salida estándar.

Llegados a este punto, hemos analizado -todo lo que el lenguaje nos permite- nuestras 5 variables. Todas parecen ser idénticas, no hay ninguna propiedad en ellas que podamos medir y que nos permitan diferenciar unas de otras.

Sin embargo, al hacer lo siguiente:

$b = new stdClass;

Al volver a repetir las evaluaciones iniciales el resultado es el siguiente:

$a === $b //FALSE
$b === $c //TRUE
$c === $d //TRUE
$d === $e //TRUE

En conclusión: 5 entidades que según el lenguaje son idénticas y por lo tanto, deben comportarse de la misma forma, tienen un comportamiento diferente; debido a propiedades internas imposibles de discernir en la capa de código.

Este es un claro ejemplo de pésimo diseño a nivel de lenguaje y, por supuesto, una fuente potencial de fuertes dolores de cabeza para cualquier programador.

Como pequeño ejercicio: ¿alguien sabe cómo hay que inicializar las 5 variables para que se comporten de la forma descrita?

Leer más

BananaDB: MySQL desde PHP

Como mucha gente me la está pidiendo y va pasando de mano en mano rulando por ahí, he decidido liberar y subir a GitHub una pequeña clase que hice hace unos meses para manejar el driver MySQLi de PHP. Se llama BananaDB (porque es un nombre que mola, y porque las siglas BDB pueden decirse en al menos dos idiomas (Banana DataBases o Bases de Datos Banana).

BananaDB

Estaréis pensando que librerías con el mismo propósito hay muchas, y es cierto. Pero me lancé a escribir la mía propia (sin muchas ganas, no me gusta rehacer la rueda si no es por diversión) porque ninguna de cuantas he probado cumple con los requisitos que yo considero esenciales. Todas ensucian mucho el código y algunas no ofrecen características esenciales para mí como las sentencias preparadas o la posibilidad de acceder al driver directamente. Esto no sólo ocurre con las librerías especializadas, cuando veo las clases controladoras de Bases de Datos que usan los grandes CMS de hoy en día es peor; y no sé si reír o llorar.

No tenía mucho tiempo para hacerla, así que es bastante sencilla. Faltan algunas features por implementar (nada que yo haya llegado a necesitar, claro). Seguramente tenga errores [ pero ahora podéis mandarme un pull request y corregirlos 🙂 o incluso completar las features que faltan 🙂 🙂 ]. La publico tal cual está. Sin testear demasiado. Pero en cualquier caso, creo que es mejor que lo que hay…

Mis metas esenciales eran (mejor explicadas, junto a otras colaterales, en la página de GitHub):

  • Escribir sentencias SQL directamente: Sin métodos, ni palabras que mezclasen las consultas. De forma que el código se mantuviera legible.
  • Poder usar sentencias preparadas (prepared statements) de forma transparente.

Repositorio y descarga

Tenéis la documentación y el código en GitHub.
O si lo preferís, un enlace al código directamente.

Sobre el desarrollo

Escribiendo la clase ha habido algunos retos interesantes que no me esperaba encontrar.

Uno muy sencillo de resolver es la concatenación de métodos en cierto orden y formando una cadena infinita (and()->and()->or()->…) y la recepción de parámetros en múltiples formatos. Creando de esta forma la sintaxis básica de uso de la clase. Tal que así:

$name=$bd->select("name")->from("fruits")->
      where("price > 100")->and("id < ", $max_id)->
      or("color = ", $color)->and ...

La llamada a un método usando como parámetros los elementos de un array (requiriendo el uso de clases reflexivas (eval no existe)) o saltarse la limitación de poder enviar opcionalmente referencias durante la llamada a un método (algo que en antiguas versiones de PHP sí se podía hacer) son otras restricciones que ha sido divertido sortear. Más que por complejidad, por demostrar una vez más lo estúpido que resulta poner limitaciones a un lenguaje (el caso de las referencias es sangrante) cuando puedes saltártelas igualmente si tienes un poco de imaginación…

Leer más

A salvo de errores… o quizá no

StormByte me ha mandado este problema para vosotros, yo esperaré un par de días y después participaré también! 🙂

Problema:

PHP es un lenguage muy dinámico, tanto, que te permite hacer muchas cosas, algunas buenas, algunas documentadas, y otras, no tan buenas y no tan documentadas.

En este caso, hablaremos del gancho (hook) que PHP pone a nuestra disposición para manejar los posibles errores con los que nos podamos encontrar y evitar que salga una advertencia que nos estropee la página.

Se trata de:

mixed set_error_handler ( callable $error_handler [,
             int $error_types = E_ALL | E_STRICT ] )

Que establece una función de usuario (error_handler) para manejar los errores de un script.

Su uso es muy sencillo, y nos permite estar a salvo de los errores que se nos puedan presentar (junto con error_reporting(0))

Este es el codigo:

<?php

error_reporting(0);

function erroresBonitos($errno, $errstr, $errfile, $errline) {
   //Manejar errores aquí, mandar un email, etc
}

set_error_handler("erroresBonitos", E_ALL);

if ($t[0])
{
   /* no se ejecuta, pero causará un warning que el
   handler maneja perfectamente sin romper nuestra web */
}

//Y finalmente, nuestra web en su bonito HTML, etc
echo "Test Mi pagina";
?>

Con esto, estaríamos a salvo de los errores que se nos puedan presentar, podríamos enviar un email al admin web, guardar el error en la base de datos, e incluso decirle al usuario que nos contacte, pero… ¿estamos seguros del todo?

La respuesta es NO, aún quedan algunos casos para los que no estamos protegidos, y para poder confiar en un handler de errores, tiene que manejar el 100% de los casos.

Con lo que este problema tiene 2 preguntas:

1.- ¿Qué podría ir mal y “saltarse” este handler de errores?

2.- ¿Podríamos protegernos de los casos de la pregunta 1 de alguna forma? Si es así, ¿Cómo podríamos hacerlo?

Esperamos unos días como de costumbre, y si no aparecen respuestas o van muy desencaminadas desvelamos la primera y dejamos algo más de tiempo para la segunda.

Leer más

Para cada uno de mis descuidos…

Un problema rápido en PHP, un lenguaje que todo el mundo dice conocer… y del que en realidad muy pocos tienen algo de idea:

<?php

class Fruit
{
   function __construct($name)
   {
      $this->name=$name;
      $this->stock['current']=array('value' => 3);
      $this->stock['cache']=array('value' => 3);
   }

   function setStock($new_stock)
   {
      foreach($this->stock as $key => $current_stock)
      {
         $current_stock['value']=$new_stock;
      }
   }
}

$fruits=array(
   "apple" => new Fruit("Apple"),
   "peach" => new Fruit("Peach")
);

//Run!

foreach($fruits as $fruit)
{
   $fruit->setStock(8);
   echo $fruit->name." = ".$fruit->stock['current']['value']."\n";
}

foreach($fruits as $fruit)
{
   $fruit->stock['current']['value']=8;
   $fruit->stock['cache']['value']=8;
   echo $fruit->name." = ".$fruit->stock['current']['value']."\n";
}

Este código saca por pantalla:

Apple = 3
Peach = 3
Apple = 8
Peach = 8

¿Por qué en el primer foreach no funciona el setStock a 8? ¿Por qué en el segundo sí? Dad una explicación y proponed alguna solución para arreglarlo. El premio para el primero que acierte es, como de costumbre, es una botella de kilkenny 😉

kilkenny-02-300x251

Leer más