Novedades al pasar de PHP 7.1 a 7.2

Sus nuevas características (2020-05-31)

PHP 7.2 changelog + casos de uso

Continuando con esta serie de post que busca comentar aquellos grandes cambio en favor de mejorar la experiencia de los desarrolladores con el lenguaje, esta vez toca a la versión 7.2.

Esta agrega algunas cuestiones nuevas con foco en mejorar rendimiento y la seguridad, aunque realiza un alto foco en efectivizar la obsolescencia de ciertas funciones y dar comienzo a desestimar el uso de otras.

Ampliación de tipos de parámetros (Parameter Type Widening)

Nos permite remover el type hint de los parámetros de una función ya sean de una clase padre o una interfaz en el objeto donde se hereda o implementa la misma.

Ampliando la posibilidad de recibir cualquier tipo de dato (any comparando con el mundo TypeScript), aunque se podría realizar cualquier validación manual en cuanto a tipos o conformidad de los datos dentro del método sin problema.

   <?php
      abstract class ParentClass {
          abstract public function methodOne(array $list): int;
      }

      class ChildClass extends ParentClass {
          public function methodOne($list): int {
              // Do your own checks for type or data
              if(!is_numeric($list)){
                  return 0;
              }
              return (int) $list;
          }
      }
      echo (new ChildClass())->methodOne(100);
      // 100

Seguramente a primera vista esto parece un retroceso en el hecho de tipado estricto, aunque tuvo lugar para poder brindar un proceso de actualización a las clases para usar type hints en las librerías sin tener que actualizar todas las subclases.

Además, puede ser una estrategía viable de momento para implementar patrones de diseño como el CommandHandler, ya que al no contar un con un soporte para generics, esto pueda ser un bypass para implementarlo.

<?php
interface ICommand {
}

class GreetingMyNameCommand implements ICommand {
    private $name = '';
    public function __construct(string $name) {
        $this->name = $name;
    }
    public function name() :string {
        return $this->name;
    }
}

interface ICommandHandler {
    public function handle(ICommand $command) :void;
}

abstract class AbstractCommandHandler implements ICommandHandler {
    final public function handle($command) :void {
        if(!$this->validateCommand($command)) {
            throw new InvalidArgumentException(static::class." invalid command for it: ".get_class($command));
        }
        $this->runCommand($command);
    }        
    abstract protected function validateCommand(ICommand $command) :bool;
    abstract protected function runCommand(ICommand $command) :void;
}

class GreetingCommandHandler extends AbstractCommandHandler {
    private $greetingString = '';
    public function __construct(string $greetingString) {
        $this->greetingString = $greetingString;
    }
    protected function validateCommand($command) :bool {
        return $command instanceof GreetingMyNameCommand;
    }
    protected function runCommand($command) :void{
        echo $this->greetingString}.' '.$command->name() . PHP_EOL;
    }
}

$cmdToRunOk = new GreetingMyNameCommand("Luciano");
$cmdToFail = new StdClass;
$cmdHandler = new GreetingCommandHandler("Hola estimado/a");
$cmdHandler->handle($cmdToRunOk);
// 'Hola estimado/a Luciano'
$cmdHandler->handle($cmdToFail);
// Fatal Error: Uncaught InvalidArgumentException: GreetingCommandHandler invalid command for it: stdClass.....

Tipo object como parámetro o retorno

Esta funcionalidad puntualmente esta orientada a mejoras en el core del lenguaje y que por transitividad quedan a nuestra disposición. El utilizar el tipo object como tipo de un parámetro o de retorno en una función.

  <?php
  declare(strict_types=1);
  function example(object $paramObject) :object {
      $stdClass = new StdClass();

      $stdClass->objectType = get_class($paramObject);
      $stdClass->objectProperties = get_object_vars($paramObject);

      return $stdClass;
  }

Utilización de coma final en los grupos de USE

Este es un detalle trivial, pero que favorece la no ocurrencia de errores por detalles superfluos como el dejar la coma en el ultimo tramo de nombre en el grupo para el namespace.

<?php
// PHP 7.0 o 7.1
use App\Repositories\{
    Model\Customer,
    Model\Address,
    MySql\MySqlCustomerRepository
};
 use App\Repositories\{
    Model\Customer,
    Model\Address,
    MySql\MySqlCustomerRepository,
};
// ERROR //


// PHP 7.2+, ambas formas funcionan
use App\Repositories\{
    Model\Customer,
    Model\Address,
    MySql\MySqlCustomerRepository
};
use App\Repositories\{
    Model\Customer,
    Model\Address,
    MySql\MySqlCustomerRepository,
};

En la versión 7.0 o 7.1 esta segunda forma nos generaría un error, pues ya no más ! Reafirmo que es un detalle minimista como para que nos genere un error, más que mejora le podemos ver como un hotfix.

Conteo en objetos no contables

Llamar la función count sobre un tipo primitivo(también denominados escalares) o en un objeto que no implementa la interface Countable lanzara un Warning aunque continuara retornando lo que solía hacer hasta el momento.

<?php
echo count(6);
echo count(7.5);
echo count('test');
echo count(true);

// Todas estas ejecuciones anteriores mostraran un WARNING y retornaran el entero UNO(1)

echo count(null);
// Aquí un caso particular y que exceptua la regla, nos muestra el WARNING, aunque retornara CERO(0)

Avances en seguridad

  • Argon2: Es un algoritmo de hashing que viene a ser una alternativa de mayor seguirdad al actual disponible Bcrypt. Este se introduce en el lenguaje mediante la constante PASSWORD_ARGON2I, que ahora se puede utilizar en funciones password:

    <?php echo passwordhash( 'password', PASSWORDARGON2I);

    Este caso tambien adiciona opciones para enviarle que concideran pen su generación parametros de costo de memoria, tiempo y paralelismo.

  • Libsodium: En esta se incluye la libreria Sodium en el nucleo que nos permite encriptar, desencriptar, firmar, crear hashes y demas que puedes interiorizarte aquí Como dato colorido con esta lib, PHP 7.2 fue el 1er lenguaje en incluirla.

Funciones/características obsoletas.

El listado a continuación esta comprendido por funciones que dejaran de existir en la version 8.0 de PHP y por ende desde la versión que estamos describiendo se sugiere su dessuso y se brinda alternativas en algún caso.

  • __autoload ha sido reemplazada por splautoloadregister en PHP 5.1. Ahora se generará un aviso de obsolescencia cuando se detecta durante la ejecución.

  • create_function() permite la creación de una función con un nombre dinámico, se recibe por parámetro, una lista de argumentos y un código de cuerpo proporcionados como argumentos. Debido a problemas de seguridad y bajo rendimiento, se ha marcado como obsoleto y, en su lugar, se recomienda el uso del concepto/clase Closure.

  • each() permite iterar sobre un array/iterable, pero con la contraparte de ser 10 veces mas lenta que la funcion foreach().


DISCLAIMER: Inteté cubrir a mi parecer lo mas relevante o lo que más útil fue para mi labor diario, para el resto ~~MasterCard~~, no mentira fuera de broma el changelog full lo pueden ver en la página oficial de PHP aquí).