¿Qué hay de nuevo en PHP 8.2? Funciones, obsolescencias y cambios importantes

Este artículo proporciona una descripción general de las nuevas características y obsolescencias de PHP 8.2. PHP 8.0 ya sentó una base sólida para estas y las próximas mejoras. El plan original para lanzar PHP 8.2 era el 24 de noviembre de 2022, pero se pospuso para el 8 de diciembre de 2022.

En este artículo, cubrimos las novedades de PHP 8.2. Nos centramos en las nuevas funciones, la desactivación y los cambios importantes. Al final del artículo encontrará una lista de referencias oficiales que documentan todos los cambios en los detalles.

PHP 8.2: nuevas funciones, cambios importantes y funciones obsoletas

¿Qué hay de nuevo en PHP 8.2?

Clases de solo lectura

PHP 8.1 introducido readonly propiedades. Con esto, los desarrolladores pueden definir propiedades de clase que se inicializan solo una vez en el alcance de su declaración. PHP 8.2 se basó en esto agregando una función para declarar toda la clase como readonly.

¿Cómo ayuda esto a los desarrolladores?

Bueno, anteriormente en PHP 8.1 podíamos tener clases con muchos parámetros de solo lectura.

class ClassWithReadOnlyParameters
{
    public readonly int $parameter1;
    public readonly string $parameter2;
    public readonly int $parameter3;
    public readonly array $parameter4;
    public readonly int $parameter5;
}

En PHP 8.2 podemos declarar toda la clase como readonly. De esta manera, todas las propiedades dentro de la clase heredarán automáticamente readonly estado.

readonly class ClassWhichIsReadOnly
{
    public int $parameter1;
    public string $parameter2;
    public int $parameter3;
    public array $parameter4;
    public int $parameter5;
}

No es posible declarar readonly sobre características específicas de PHP:

Sin embargo, es posible declarar clases abstractas y finales como readonly.

abstract readonly class AbstractClass {}
final readonly class FinalClass {}

Finalmente, es posible declarar readonly en una clase que no tiene propiedades. En este caso, las clases secundarias podrían declarar sus propiedades de solo lectura.

nulo, verdadero y falso como tipos independientes

PHP 8.2 continúa mejorando la seguridad de tipos al introducir null y false como tipos independientes.

¿Qué significa un tipo independiente?

Anteriormente, podíamos utilizar estos tipos como parte de la unión, es decir int|false o string|false.

function calculateNumberOrReturnFalse(): int|false
{
    // ...business logic...
    if ($calculationPossible) {
        return $calculation; // return integer
    }

    return false;
}

Ahora, desde PHP 8.2 es posible utilizar null y false como tipos independientes.
Por ejemplo:

function alwaysReturnTrue(): false
{
    // ...business logic...
    return false;
}

Por supuesto, los nuevos tipos independientes no pretenden reemplazar el manejo adecuado de errores, ni el lanzamiento y la captura de errores. Sin embargo, en casos de funciones escritas correctamente con una razón válida para devolver siempre verdadero, falso o nulo, es posible escribir estrictamente el parámetro de retorno.

Finalmente, este cambio viene con una advertencia. No es posible utilizar true y false tipos en la unión como true|false. Esto tiene sentido, porque la unión de los true y false sería una característica redundante porque es esencialmente una boolean tipo.

Tipos de forma normal disyuntiva

La forma normal disyuntiva (DNF) es una forma estandarizada de organizar expresiones booleanas. Es decir, con tipos de forma normal disyuntiva es posible estructurar expresiones booleanas con AND y OR.

Para comprender esta característica específica, actualicemos rápidamente nuestro conocimiento sobre dos características de PHP:

  • tipos de unión
  • tipos de intersecciones

PHP 8.0 introdujo los tipos de unión y esta característica permite declarar propiedades, parámetros o tipos de retorno con múltiples tipos.

private int $commonSingleTypeVariable;
private int|float $twoTypesVariable;

PHP 8.1. introdujo los tipos de intersección, como una característica algo opuesta a los tipos de unión. Tipos de intersección permite declarar que un valor específico pertenece a todas las clases o tipos de interfaz declarados.

public function exampleFunction(Interface1&Interface2 $bothStringAndIntValue)
{
    // business logic
}

Ahora, PHP 8.2 introdujo los tipos de forma normal disyuntiva (DNF) como una forma de combinar tipos de unión y tipos de intersección. Sin embargo, existe una regla estricta al respecto. Al combinar tipos de unión e intersección, los tipos de intersección deben agruparse entre corchetes.

function disjunctiveNormalFormTypesExample((Interface1&Interface2)|null $wellTypedVariable) {

    if (null === $wellTypedVariable) {
        return $something; // or null for example
    }

    // ... otherwise continue with the business logic
}

El (Interface1&Interface2)|null $wellTypedVariable representa DNF y significa: la variable $wellTypedVariable debe implementar métodos tanto de la Interfaz1 como de la Interfaz2 o puede ser un valor anulable.

Los rasgos ahora admiten constantes

A partir de PHP 8.2, los rasgos admiten constantes.

trait ReusableCode
{
    public const IMPORTANT_CONSTANT = 3600;
}

Sin embargo, no es posible utilizar la constante dentro del rasgo mismo. Sólo es posible utilizar esta constante dentro de la clase que utiliza ese rasgo.

Por ejemplo:

trait ReusableCode
{
    public const IMPORTANT_CONSTANT = 3600;

    public function reusableFunction(int $importantVariable): string
    {
        // It is NOT allowed using constant within the trait
        if ($importantVariable > ReusableCode::IMPORTANT_CONSTANT) {
            return false;
        }
    }
}

// However once we use the trait within the class
class ExampleClass
{
    use ReusableCode;
}

// It is allowed to use constant from the trait used within the class
ExampleClass::IMPORTANT_CONSTANT;

Redacción de parámetros en rastros anteriores

Cuando nuestro código base termina en estado de error, esto genera un seguimiento con todos los detalles, incluidos los valores almacenados dentro de los parámetros. Normalmente reenviamos estos rastreos a diferentes servicios para realizar un seguimiento de errores y advertencias. Se trata de servicios como Sentry.io, Elastic, Datadog, Amazon CloudWatch, etc.

Si bien esto puede estar bien para entornos de desarrollo y pruebas, en los entornos de producción tratamos con datos confidenciales. Muy a menudo tenemos que escribir diferentes mecanismos de filtrado para asegurarnos de que los parámetros y datos confidenciales no queden expuestos en los registros.

PHP 8.2 viene con una gran característica para redactar parámetros en rastros anteriores. Es súper sencillo. Podemos anotar atributos sensibles con #[\SensitiveParameter] y esto indicará a PHP que filtre este valor en los rastros anteriores. El parámetro sensible será reemplazado por Object(SensitiveParameterValue)).

El RFC original (ver referencias) tiene ejemplos fantásticos sobre cómo funciona esto.

Aquí hay un caso de uso básico:

function test(
    string $foo,
    #[\SensitiveParameter] string $privateKey,
    string $baz
) {
    throw new \Exception('Any Exception');
}

test('foo', 'sensitive_parameter-private_key', 'baz');

/*
Fatal error: Uncaught Exception: Error in example.php:10
Stack trace:
#0 test.php(...): test('foo', Object(SensitiveParameterValue), 'baz')
*/

Como se puede ver, sensitive_parameter-private_key no será parte del rastreo hacia atrás. En lugar de eso, será reemplazado por Object(SensitiveParameterValue). ¡Limpio!

Extensión aleatoria 5.x

En resumen, PHP 8.2 introduce un nuevo generador de números aleatorios que resuelve muchos problemas conocidos. El nuevo generador de números aleatorios es un solo Randomizer clase que proporciona diferentes métodos de aleatorización. Nuevo Randomizer funciona mejor y no depende del estado global.

Por ejemplo:

$randomizer = new Random\Randomizer(); // default engine is Random\Engine\Secure()

$randomInt = $randomizer->getInt(); // replaces mt_rand()
$randomRangedInt = $randomizer->getInt(1,100); // replaces mt_rand() and random_int()
$randomBytes = $randomizer->getBytes(10); // replaces random_bytes()
$shuffledArray = $randomizer->shuffleArray(['1','2','3']);  // replaces shuffle()
$shuffledString = $randomizer->shuffleString('abcdefg'); // replaces str_shuffle()

Obtener propiedades de enumeraciones en expresiones constantes

En resumen, PHP 8.2 permite el uso de ->/?-> operador para recuperar propiedades de enumeraciones en expresiones constantes. Según RFC para esta característica, la motivación principal era permitir recuperar las propiedades de nombre y valor en lugares donde antes no era posible, como en matrices.

Por ejemplo:

// This is not possible before PHP 8.2
const C = [self::B->value => self::B];

¿Qué características están obsoletas en PHP 8.2?

Desaprobar propiedades dinámicas

Las propiedades dinámicas en PHP permitieron a los programadores crear una instancia de un objeto y asignarle una propiedad que no existe en la clase original. A esto lo llamamos establecer y recuperar dinámicamente propiedades de clase no declaradas. Desde PHP 8.2, esto generará advertencias de desaprobación y el plan es desaprobarlo en PHP 9.0.

class Foo {
 private string $bar;
}

$instance = new Foo();

// From PHP 8.2 this will throw a deprecation warning 
// From PHP 9.0 this will throw an ErrorException
$instance->newProperty = 'anything';

PHP 8.2 proporciona una manera de silenciar las advertencias de obsolescencia para la creación de propiedades dinámicas usando #[AllowDynamicProperties] notación.

#[AllowDynamicProperties]
class Foo {
 private string $bar;
}

$instance = new Foo();

// Will not throw a deprecation warning
$instance->newProperty = 'anything';

Dejar de utilizar invocables parcialmente admitidos

Hasta PHP 8.1 hay invocables que son aceptados por el tipo invocable, también por el is_callable() función y call_user_func(). Sin embargo, no cuentan con el apoyo de $callable().

Lista de estos invocables

"self::method"
"parent::method"
"static::method"
["self", "method"]
["parent", "method"]
["static", "method"]
["Foo", "Bar::method"]
[new Foo, "Bar::method"]

Sin embargo, para facilitar las cosas, la mayoría de los invocables obsoletos tienen un reemplazo sencillo: «self» debe reemplazarse por self::class.

"self::method"       -> self::class . "::method"
"parent::method"     -> parent::class . "::method"
"static::method"     -> static::class . "::method"
["self", "method"]   -> [self::class, "method"]
["parent", "method"] -> [parent::class, "method"]
["static", "method"] -> [static::class, "method"]

Funciones obsoletas utf8encode() y utf8decode()

Estas dos funciones PHP integradas codificaron “Latin 1” (ISO-8859-1) en “UTF-8” y decodifican UTF-8 en latín. Las funciones son útiles, pero tienen desventajas. En primer lugar, sus nombres sugieren que cualquier entrada proporcionada se puede convertir a UTF-8, lo cual no es correcto. En segundo lugar, las funciones carecen de mensajes de error, lo que significa que no es fácil reconocer un uso incorrecto.

RFC afirma que, según la encuesta de abril de 2021 realizada a 1000 paquetes ordenados por popularidad de Packagist, de 37 paquetes que usaban estas funciones, solo 4 bibliotecas las usaban claramente correctamente.

Finalmente, RFC también sugiere alternativas a la funcionalidad eliminada. El más interesante es el más utilizado, para la conversión de caracteres, que afirma que ext/mbstring es probablemente uno de los más utilizados.

ext/mbstring: $utf8 = mb_convert_encoding($latin1, 'UTF-8', 'ISO-8859-1'); and $latin1 = mb_convert_encoding($utf8, 'ISO-8859-1', 'UTF-8');

ext/intl: $utf8 = UConverter::transcode($latin1, 'UTF8', 'ISO-8859-1'); and $latin1 = UConverter::transcode($utf8, 'ISO-8859-1', 'UTF8');

ext/iconv: $utf8 = iconv('ISO-8859-1', 'UTF-8', $latin1); and $latin1 = iconv('UTF-8', 'ISO-8859-1', $utf8);

Desaprobar la interpolación de cadenas ${}

En PHP, los programadores incrustan variables en cadenas con comillas dobles y en heredoc. A esto lo llamamos interpolación de cadenas. Hay varias formas de lograr la interpolación de cadenas.

  1. Incorporación directa de variables “$foo”
  2. Llaves fuera de la variable “{$foo}”
  3. Frenos después del signo de dólar “${foo}”
  4. variables variables “${expr}” que es equivalente a (string) ${expr}

Si bien las opciones 1 y 2 tienen sus pros y sus contras, en el RFC se describen las opciones 3 y 4 como fácilmente confusas debido a la sintaxis superpuesta. Además, la opción 3 es menos capaz que la 1 y la 2, y la opción 4 tiene una semántica completamente diferente.

Por lo tanto, RFC propuso desaprobar las opciones 3 y 4.

var_dump("${foo}");
// Deprecated: Using ${} in strings is deprecated

var_dump("${(foo)}");
// Deprecated: Using ${} (variable variables) in strings is deprecated

RFC también propone rutas de migración, como la forma más sencilla de implementar este cambio.

Migrar “llaves después del signo de dólar” a “llaves fuera de la variable”, opción 3 a opción 2.
Sencillo, simplemente moviendo el signo del dólar dentro de las llaves.

"${foo}" => "{$foo}"
"${foo[expr]}" => "{$foo[expr]}"

Migrando “variables variables” a “llaves fuera de la variable”, opción 4 a opción 2.
También es sencillo, simplemente agregando llaves alrededor de toda la interpolación.

"${foo->bar}" => "{${foo->bar}}"

Desuso de funciones mbstring para entidades Base64/QPrint/Uuencode/HTML

PHP 8.2 desaprobó el uso de ‘codificaciones de texto’ QPrint, Base64, Uuencode y HTML-ENTITIES para todas las funciones mbstring.

Esta desaprobación se produce por varios motivos:

  1. Estos casos tratan con secuencias de bytes sin formato, por lo que no está claro cuál es el valor correcto para la función mbstring.
  2. PHP tiene una implementación existente y separada para manejar estas codificaciones.

El uso de funciones mbstring con valores obsoletos generará algunas de las siguientes advertencias

Deprecated: mb_check_encoding(): Handling HTML entities via mbstring is deprecated; use htmlspecialchars, htmlentities, or mb_encode_numericentity/mb_decode_numericentity instead...

Deprecated: mb_strcut(): Handling HTML entities via mbstring is deprecated; use htmlspecialchars, htmlentities, or mb_encode_numericentity/mb_decode_numericentity instead...

Deprecated: mb_convert_encoding(): Handling QPrint via mbstring is deprecated; use quoted_printable_encode/quoted_printable_decode instead...

Deprecated: mb_convert_encoding(): Handling Base64 via mbstring is deprecated; use base64_encode/base64_decode instead in...

Deprecated: mb_convert_encoding(): Handling HTML entities via mbstring is deprecated; use htmlspecialchars, htmlentities, or mb_encode_numericentity/mb_decode_numericentity instead...

Deprecated: mb_strlen(): Handling Base64 via mbstring is deprecated; use base64_encode/base64_decode instead...

Deprecated: mb_strlen(): Handling HTML entities via mbstring is deprecated; use htmlspecialchars, htmlentities, or mb_encode_numericentity/mb_decode_numericentity instead...

Todo lo que necesita saber sobre la nueva actualización de PHP 8.2: resumen rápido

PHP 8.2 se lanza el 8 de diciembre. Viene con muchas características interesantes, como clases de solo lectura, características que admiten constantes, redacción de parámetros de seguimientos anteriores, etc. Como en las versiones anteriores, PHP tiene como objetivo limpiar problemas heredados y estandarizar los enfoques de codificación que podemos ver en características obsoletas como las propiedades dinámicas. , invocables parcialmente compatibles y optimización de la interpolación de cadenas. PHP 8.2 también mejora la seguridad y el rendimiento, por ejemplo al introducir un nuevo generador de números aleatorios.

¿Qué hay de nuevo en PHP 8.2?

  1. Las clases de solo lectura nos permiten definir toda la clase como de solo lectura, que se aplica automáticamente a todos los parámetros de esta clase.
  2. nulo, verdadero y falso como tipos independientes nos permiten establecer el tipo de retorno en null,true o false
  3. Los tipos de forma normal disyuntiva nos permiten combinar tipos de unión con tipos de intersección en expresiones booleanas.
  4. Los rasgos ahora admiten constantes, pero no se pueden usar dentro de los rasgos, solo dentro de clases que usan rasgos.
  5. Se pueden anotar parámetros sensibles y PHP los enmascarará automáticamente en los rastros anteriores.
  6. Se ha mejorado el generador de números aleatorios y se han solucionado los principales problemas de rendimiento en la nueva extensión aleatoria 5.x.
  7. Ahora es posible recuperar propiedades de enumeraciones dentro de expresiones constantes, es decir, dentro de las matrices.

¿Qué está en desuso en PHP 8.2?

  1. Las propiedades introducidas fuera de la descripción de clase «Propiedades dinámicas» ya no están permitidas.
  2. Los callables que no fueron aceptados por todas las funciones de PHP como «Callables parcialmente compatibles» ya no están permitidos.
  3. Utf8encode() y Utf8decode() ahora están obsoletos debido a su funcionalidad confusa y su mal uso histórico.
  4. De los 4 enfoques posibles de interpolación de cadenas, 2 enfoques están en desuso por ser menos capaces y redundantes.
  5. Mbstring ya no se puede utilizar para entidades Base64/QPrint/Uuencode/HTML porque existen funciones dedicadas para esto.

Source link

About Carlos Carraveo Jimenez

Check Also

Deja de «pintarle lápiz labial a un cerdo», es hora de innovar

La frase «ponerle lápiz labial a un cerdo» es una forma coloquial de describir el …

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *