archivo

PHP

Presentación de Davey Shafik –@dshafik– en la PHP[Architec] ’13 con las novedades de la versión 5.5 de PHP:

new-in-php-5-5

Anuncios

Aunque el título suene atractivo, PHP no ha incorporado la herencia múltiple como tampoco lo hace Java pero si que desde la versión >= 5.4 incorpora un mecanismo llamado Traits que simularía la herencia múltiple de clases. Los Traits son usa especie de clases cuya misión es agrupar funcionalidades comunes. Este tipo de clases no se puede instanciar directamente sino que se emplea en una clases. Ejemplo:


trait base1 {

  function metodo1(){ return 'metodo1'; }

  function metodo2(){ return 'metodo2' }

}

class base2 {

  function metodo1(){ return 'base2:metodo1' }

}

class miClase extends base2 {

  use base1;

}

Mediante la palabra reservada use, incorporamos la funcionalidad contenida en el trait base1 y mediante extends incorporamos la funcionalidad de base2. Como vereis, base1 y base2 comparten nombres de métodos comunes. Para solventar conflictos, existe una precedencia: Miembros de clase actual -> miembros del trait -> miembros heredades (extends), es decir, los miembros de miClase tienen precedencia sobre los de base1 y base1 tiene precedencia sobre los de base2.

Insertar multiples traits es muy sencillo:

use traitClass1, traitClass2, traitClassN

Resolución de conflictos entre Traits

En algunas ocasiones varios traits comparten nombres de métodos y si el conflicto no se resuelve genera un error fatal. Para resolver un conflicto disponemos de los operadores as e insteadof.

trait base1 {

  function metodo1(){ return 'metodo1'; }

  function metodo2(){ return 'metodo2' }

}

trait base2 {

  function metodo1(){ return 'base2:metodo1'; }

  function metodo2(){ return 'base2:metodo2' }

}
use base1, base2 {
base1::metodo2 insteadof base2;
base2::metodo1 insteadof base1;
}

No es la herencia múltiple de Python pero no está mal la aproximación. Preferiría que en futuras versiones resolviesen los conflictos de una manera más transparente con algún tipo de convención.

La teoría dice que para instalar PHPUnit en Ubuntu (Xubuntu y otros sabores) 12.04 sería usando el comando apt-get:

sudo apt-get install phpunit

La práctica es algo distinta. La instalación con el método anterior genera errores del tipo:

PHP Fatal error: Call to undefined method PHP_CodeCoverage_Filter::getInstance() in /usr/bin/phpunit on line 39

o este otro:

PHP Fatal error:  require_once(): Failed opening required 'PHP/CodeCoverage/Filter.php'

La solución que me ha funcionado: (escrita por Anthony en stackoverflow)

sudo apt-get remove phpunit //Si lo instalaste con apt-get
sudo pear channel-discover pear.phpunit.de
sudo pear channel-discover pear.symfony-project.com
sudo pear channel-discover components.ez.no
sudo pear update-channels
sudo pear upgrade-all
sudo pear install --alldeps phpunit/PHPUnit
sudo pear install --force --alldeps phpunit/PHPUnit

Criteria es el objeto que permite definir los criterios de selección de resultados en sistemas que emplean Propel como ORM. Propel y Doctrine son dos plataformas de mapeo de resultados SQL a clases empleados por Symfony. Este post se centra en el uso de Propel y describo como emplear funciones SQL propias en el objeto Criteria.

Imagina que tenemos una tabla llamada producto con dos campos:

  • id
  • nombre

En el modelo de clases generado por Symfony tendremos una clase llamada ProductoPeer que es la encargada de realizar los accesos a base de datos. Para realizar las consultas hemos de construir un objeto Criteria que contiene las características de los datos que deseamos seleccionar. En algunas ocasiones es útil emplear funciones que hemos escrito en base de datos, como por ejemplo, una función que dado un id de producto nos devuelve el número de veces que se ha consultado en nuestra web. El código lógico sería el siguiente:

$criteria = new Criteria();

$criteria->addAsColumn(‘consultas’, ‘getConsultasProducto(‘.ProductoPeer::ID.’)’);
$criteria->add(ProductoPeer::ID, $productoId);
ProductoPeer::doSelect($criteria);

getConsultasProducto es una función de base de datos que devuelve el número de consultas.

Si lanzamos la aplicación dará un error indicando que ProductoPeer no puede encontrar el campo con la clave primaria. Para evitar esto usamos lo siguiente:

$criteria = new Criteria();
$criteria->clearSelectColumns();
$criteria->addSelectColumn(self::ID);
$criteria->addSelectColumn(self::NOMBRE);
$criteria->addAsColumn('consultas', 'getConsultasProducto('.ProductoPeer::ID.')');
$criteria->add(ProductoPeer::ID, $productoId);
ProductoPeer::doSelect($criteria);

Lo nuevo con respecto al código inicial es que se resetean los campos que estarán en la select y se añaden en el mismo orden en el que están declarados en config/schema.yml del proyecto. Gracias a esto, podemos ordenar los resultados por el número de consultas del producto:

$criteria->addDescendingOrderByColumn($criteria->getColumnForAs('consultas'));

Espero que sea de utilidad. Saludos.

Las cookies son pequeños fragmentos de información que las páginas web envían al navegador  para recordar cierta información en el futuro. Se almacenan de forma local, es decir, cada usuario las almacena en un archivo de su máquina. Las cookies pueden contener información simple, como una cadena de texto, pero también pueden tener información compleja. Por ejemplo, imagine una tienda tipo ebay en las que se almacenan los últimos productos visitados y en función de ello, ofrecerte nuevas ofertas similaes a lo que has buscado. Sin duda, esto mejora la experiencia del usuario.

Este post trata de cómo almacenar información estructurada en una cookie para luego obtenerla fácilmente. Una de las mejores formas de intercambiar información estructurada en páginas web es el formato JSON. Este es un formato ligero, fácil de usar e interpretar que ha experimentado una gran crecimiento en los últimos tiempo. Existen parsers (intérpretes) en casi todos los lenguajes y PHP lo incluye de forma nativa desde la versión 5.2.

Almacenar información estructurada en una cookie es sencillo: crea una clase y define la estructura de variables:


class miClase {
public dato1 = "valor";
public dato2 = array("entrada");
}

Este clase será serializada y convertida a JSON mediante la función json_encode:


$resultado = json_encode(miClase);

La función devuelve una cadena de texto en formato JSON. Como restricción, esta función sólo trabaja con datos en formato UTF-8. Finalmente, para no tener problemas con algunos caracteres que no pueden aparecer en las cookies, aplicamos la función urlencode y tendremos el texto listo para almacenarlo en la cookie:


setcookie('nombreCookie', $resultado);

Cuando llega una petición web, la obtención de los parámetros de la cookie se realiza con los pasos anteriores de forma inversa:


$jsonString = urldecode($datosCookie);
$datos = json_decode($jsonString, true);

La variable $datosCookie contien los datos JSON almacenados anteriormente. Finalmente $datos contiene un array asociativo con los datos originales. Este array se obtiene debido a que hemos empleado el valor true en el segundo parámetro de la función json_decode. Si no se emplea este segundo parámetro,  json_decode devuelve un objeto.

Que los dispositivos móviles, como los smartphones o las tablets, han llegado para quedarse es un realidad innegable. Para todos ellos existe varios sistemas operativos: iOS, Android, BlackBerry OS, Symbian, Palm… etc. A su vez, estos contiene aplicaciones, tales como los navegadores, que se han convertido en una de las aplicaciones más importantes de estos dispositivos. Disponer una versión para móvil de nuestra página web es muy recomendable y para poder mostrarla es necesario detectar cuando el agente o navegador proviene de una plataforma móvil. Hoy os presento Detect Mobile Browsers una web que, mediante un sencillo formulario,configuramos las acciones que se realizarán cuando se detecte el user-agent de navegadores móviles como el de iPhone, iPad, Android…

Formulario de captura

El resultado de completar el formulario es una función llamada mobile_device_detect con los parámetros adecuados para llevar a cabo las reglas configuradas. Dicha función se encuentra en un fichero PHP que podemos descargar. Para usarlo es necesario realizar un include: require_once('mobile_device_detect.php'); $mobile = mobile_device_detect(param1, param2, ...); En el fichero PHP que incluimos hay escritas una gran cantidad de expresiones regulares para detectar los principales navegadores. Además, si el user-agent no coincide con el de algún navegador conocido, emplea patrones usados por los principales operadores de telefonía en el user-agent de los sistemas operativos que personalizan. El código generado se acompaña con una licencia propia que indica la posibilidad de usarlo en un sitio web sin coste alguno siempre que la web no presente actividad comercial.

Actualización 29/12/2012:

Han aparecido numerosos proyectos para detectar el dispositivo desde el que se accede a una web o web app. Entre ellos, el que recomienda Conchi en el comentario: Mobile detect, un proyecto Open source en Github. Además, si como en mi caso, desarrollas con Symfony 2, existe un bundle llamado MobileDetectBundle que  lo incorpora.

A %d blogueros les gusta esto: