php55
PHP 5.5 se lanzó el pasado 20 de junio, y pronto anunciamos su soporte en los VPS de ServerGrove. Desde entonces, muchos usuarios han actualizado sus servidores virtuales a PHP 5.5 para aprovechar las mejoras de rendimiento y algunas de sus nuevas características. Aquí hablamos de algunas de las mejoras más significativas:

Generadores

Los generadores, básicamente, simplifican el proceso de implementar iteradores. Cualquier funcion que contenga la palabra clave yield se convierte automáticamente en una función generadora.

Imagina que quieres recorrer una lista de millones de números. Sin iteradores, tendrías que crear un array enorme primero y recorrerlo después, con el correspondiente consumo de memoria. Esto se puede evitar usando iteradores, ya que los números son producidos en cada iteración. Los generadores permiten crear los iteradores sin todo el código extra necesario para crear iteradores.

<?php
function getList($number) {
    for ($i=0;$i<$number;$i++) {
        yield $i;
    }
}

foreach (getList(10000000) as $number) {
    echo "$number ";
}

La salida sería:

0 1 2 3 4 5 6 ...

He creado un benchmark sencillo para comparar la memoria usada para 10.000 números, suficiente para ver la diferencia de consumo:

Creating array: 26.60 Mb
Generator: 12.60 Mb

Try-catch… y ¡finally!

Los bloques try-catch tienen ahora un nuevo amigo: finally. El código del bloque finally debe ejecutarse tanto si la excepción se ha lanzado o no. Esto asegura también que el bloque finally se ejecutará incluso si se lanza una excepción no contemplada.

<?php
try {
    $db = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
}
catch (Exception $e) {
    echo 'catch' . "\n";
}
finally {
    echo 'finally';
}

En caso de que la conexión a la base de datos falle, los bloques catch y finally se ejecutarán. Y si la conexión es correcta, solo el bloque finally:

// database connection fail
catch
finally

// database connection ok
finally

empty() acepta ahora expresiones

Seguro que más de una vez has intentado hacer algo como empty($user->getName())… ¿verdad? Es abstante molesto tener que crear una nueva variable con el resultado de la función solo para poder pasarla a empty(). En PHP 5.5, esto ya no es necesario, ya que acepta expresiones:

<?php
echo (int) empty(0) . "\n";
echo (int) empty(1) . "\n";
echo (int) empty("") . "\n";
echo (int) empty("hello") . "\n";
echo (int) empty(empty(empty(0)));

The output:

1
0
1
0
1

Si te estás preguntando por qué la última línea devuelve 1/true, recuerda que empty() considera como vacío “”, 0, 0.0, “0″, NULL, FALSE y array(). Por lo tanto, empty(0) es true, empty(true) false y por último empty(false) es true.

Como curiosidad, el RFC original incluía también a isset(), pero fue finalmente desechada para evitar confusiones.

Array/string deferencing

Se puede acceder directamente a literales y arrays estáticos para acceder a elementos o caracteres individuales.

<?php
echo [1, 2, 3][0] . "\n";
echo array(1, 2, 3)[1] . "\n";
echo "hello"[0];

La salida sería:

1
2
h

FQN de clases usando ::class

Antes de PHP 5.5, si queríamos obtener el FQN de una clase teníamos que usar Reflection o instanciar la clase para pasarla a la función get_class(). Era común definir constantes para superar esta limitación (p.ej. ClassName::CLASS_NAME). Ahora, es posible usar ClassName::class para obtener el FQN de la clase ClassName.

<?php
namespace Foo;
class Bar {}

echo Bar::class;

La salida sería:

Foo\Bar

Es importante destacar que ::class es una palabra clave, no una constante ni un método mágico.

foreach acepta list() y claves complejas

Se ha mejorado la estructura foreach con dos nuevas características: extraer arrays anidados con list() y claves complejas (no escalares).

Con list(), los arrays anidados pueden ser extraídos en variables, lo que mejora su legibilidad:

<?php
$values = [[1, 2], [3, 4]];
foreach ($values as list($a, $b)) {
    echo $a . '-' . $b . "\n";
}

La salida:

1-2
3-4

Para claves de tipos no escalares, debe utilizarse un Iterator, ya que no es posible usarlas en arrays nativos todavía.

Extensión OPcache

Zend Optimiser+ se ha añadido a PHP como la nueva extensión OPcache. OPcache mejora el rendimiento de PHP almacenando los bytecodes precompilados en la memoria compartida. Por lo tanto, elimina la necesidad de tener que leer y parsear los scripts en cada petición. La extensión está integrada en PHP 5.5.0 y posteriores, aunque también está disponible en PECL para versiones más antiguas (5.2, 5.3 y 5.4).

Password hashing API

PHP incluye una nueva API de hashing, que nos facilita la gestión de passwords. Proporciona funciones para generar un hash de un string, obtener información de ese hash, verificarlo y comprobar si necesita ser hasheado de nuevo.

<?php
$hash = password_hash('servergrove', PASSWORD_BCRYPT); // create hash
echo $hash . "\n";
var_dump(password_get_info($hash)); // get hash info (algorithm and options)
var_dump(password_needs_rehash($hash, PASSWORD_BCRYPT)); // check if hash implements the algorithm and options provided
var_dump(password_verify('servergrove', $hash)); // check hash matches the password
$2y$10$XmxdWDeAGR7eyQOiDmRC2.RMQXko3..ELuWwpL1Qyni1gVOlAWUk2
array(3) {
  ["algo"]=>
  int(1)
  ["algoName"]=>
  string(6) "bcrypt"
  ["options"]=>
  array(1) {
    ["cost"]=>
    int(10)
  }
}
bool(false)
bool(true)

El objetivo de esta nueva API es que sea fácil de utilizar, segura y compatible con futuras versiones de algoritmos de hashing. Anthony Ferrara, el PHP core developer que propuso esta nueva API escribió un artículo realmente interesante sobre el diseño de la API. En el RFC también se puede encontrar buen contenido sobre la API y criptografía en general.

GD

Se han añadido algunas mejoras en la extensión de GD. Especialmente importante es el soporte para el formato WebP, que proporciona compresión con y sin pérdida para imágenes destinadas para web.

This post is also available in: Inglés