Desarrollo de sitio web

Nosotros Makklays. Ayudamos a realizar la idea.

¿Qué hay de nuevo en PHP 8?


Makklays - Artículos image

eye 271

Escribimos todos nuestros sitios en Makklays en lenguaje de programación PHP. Estamos interesados ​​en el desarrollo de PHP y tecnologías relacionadas con PHP. Como todos ya saben, a finales de 2020 se lanzará una nueva versión de php 8 y, a este respecto, analizaremos y ¿qué novedades habrá en ella? Entonces.

Desde la versión 7.0, la mayor parte del núcleo se ha reescrito, lo que resulta en un aumento del rendimiento de 2-3x. Cada nueva versión tiene un impacto positivo en el rendimiento, y esto se puede ver en los puntos de referencia. ¿Habrá un aumento de velocidad en PHP 8? En PHP 8, se agregará un compilador JIT a la lista de aceleradores, lo que también permitirá que PHP ingrese a nuevas áreas más allá del desarrollo web. Creo que no habrá ganancias de velocidad como en PHP 7 (tal vez un poco).

JIT: compilador Just In Time: el compilador jit tan esperado aparecerá en PHP 8. ¿Por qué tan esperado? Como los desarrolladores ya lo iban a incluir en una versión anterior, pero jit solo aparecerá en el nuevo PHP8. JIT se implementa como parte de la extensión Opcache.

Y, por cierto, recientemente me preguntaron aquí mi opinión sobre la biblioteca PEAR (los desarrolladores jóvenes ya no saben cuánto esta biblioteca era una vez demandada y popular en php, y algunos de sus elementos todavía se usan hoy en día). Entonces, creo que está desactualizado. Dado que una parte importante de sus funciones ya está en desuso (no es compatible con las nuevas versiones de php, sus funciones se han excluido de las nuevas versiones de php). Lo cual es realmente feliz. Con mis propios ojos, veo el desarrollo de php de una nueva versión a otra nueva versión de php. Pero hay un gran inconveniente: debe aprender constantemente. Explore nuevas características y nuevas bibliotecas que los desarrolladores incluyen y agreguen a php. Y hay más y más de ellos. Por qué, de hecho, la biblioteca PEAR (que no es una manzana del Jardín del Edén) fue excluida de la entrega básica de php en la versión 7.4.

Tipos de unión 2.0



PHP comienza a admitir dos tipos de datos variables al mismo tiempo.
Tipo o nulo utiliza la sintaxis especial "? Tipo"
matriz o transitable usando el tipo especial iterable
Pero los tipos de unión arbitrarios actualmente no son compatibles con php. En cambio, las anotaciones phpdoc se usan como en el ejemplo a continuación:
class Number {
/**
* @var int|float $number
*/
private $number;

/**
* @param int|float $number
*/
public function setNumber($number) {
$this->number = $number;
}

/**
* @return int|float
*/
public function getNumber() {
return $this->number;
}
}

Los tipos de unión se utilizan actualmente en todas las posiciones donde los tipos se aceptan actualmente (sintaxis T1 | T2 | ...)
class Number {
private int|float $number;

public function setNumber(int|float $number): void {
$this->number = $number;
}

public function getNumber(): int|float {
return $this->number;
}
}

Un tipo nulo que no devuelve nada no puede ser parte de un tipo de unión.
¿Y las uniones anulables se pueden escribir usando | nulo o usando? registros
public function foo(Foo|null $foo): void;
public function bar(?Bar $bar): void;


Hacer coincidir la expresión v2



La sintaxis de expresión de conmutador heredada se ha simplificado enormemente. Ha aparecido un nuevo partido. la coincidencia no requiere declaraciones de ruptura, puede devolver un valor, combinar condiciones, usar comparaciones de tipo fuerte y no realiza ningún tipo de coerción.
Fue así:
switch (1) {
case 0:
$result = 'Foo';
break;
case 1:
$result = 'Bar';
break;
case 2:
$result = 'Baz';
break;
}
echo $result;


Y se hizo así:
echo match (1) {
0 => 'Foo',
1 => 'Bar',
2 => 'Baz',
};

Si hay varias condiciones, se pueden separar por comas para ejecutar el mismo bloque de código.
$result = match($input) {
0 => "Какой-то Вывод",
'1', '2', '3' => "Вывод условий 1,2,3",
};


Promoción de propiedades de constructor



Simplificación de la sintaxis para usar propiedades en el constructor. Anteriormente, las propiedades en una clase tenían que escribirse varias veces. Considera la clase
class Point {
public float $x;
public float $y;
public float $z;

public function __construct(
float $x = 0.0,
float $y = 0.0,
float $z = 0.0,
) {
$this->x = $x;
$this->y = $y;
$this->z = $z;
}
}

Las propiedades se repitieron 1) en la declaración de propiedad, 2) en los parámetros del constructor y 3) dos veces en la asignación de propiedad. Además, el tipo de propiedad también se repite dos veces.

En php8, en lugar de especificar propiedades de clase y constructores para ellos en php, ahora puede combinarlos en uno. Como resultado, el código se reduce lo más posible:

class Point { 
público функция __construct (
lista publica $x = 0.0,
lista publica $y = 0.0,
lista publica $z = 0.0,
) { }
}


Otro ejemplo, en lugar de
class Money 
{
public Currency $currency;

public int $amount;

public function __construct(
Currency $currency,
int $amount,
) {
$this->currency = $currency;
$this->amount = $amount;
}
}

Ahora tal vez
class Money 
{
public function __construct(
public Currency $currency,
public int $amount,
) {}
}


Este código simplificado es equivalente al ejemplo anterior, pero más conciso. Y la elección de la sintaxis se tomó del lenguaje hermano Hack.

Nuevo tipo de retorno estático



Ya era posible devolver self, pero antes de PHP 8 no era un tipo de retorno estático válido. Dada la naturaleza dinámicamente tipada de PHP, esta característica será útil para muchos desarrolladores.
class Foo
{
public function method(): static
{
return new static();
}
}


Atributos



Conocemos los atributos de otros lenguajes de programación, como anotaciones o decoradores, que brindan la capacidad de agregar metadatos a las clases. El uso generalizado muestra que esta es una característica muy solicitada en la comunidad PHP. Los atributos son texto con formato especial entre comillas '<<' y '>>' al reutilizar los tokens T_SL y T_SR existentes.

Aquí hay una lista de dónde se pueden aplicar los atributos:
- funciones (incluidos cortocircuitos y cortocircuitos)
- clases (incluidas clases anónimas), interfaces, rasgos
- constantes de clase
- propiedades de clase
- métodos de clase
- parámetros y funciones

Cómo se ve en el código:
use App\Attributes\ExampleAttribute;

<>
class Foo
{
<>
public const FOO = 'foo';

<>
public $x;

<>
public function foo(<> $bar) { }
}

<>
class ExampleAttribute
{
public $value;

public function __construct($value)
{
$this->value = $value;
}
}

Le llamo la atención sobre el hecho de que puede hacer su propio Atributo, y puede aprender cómo hacer y cómo funcionan los atributos leyendo esta publicación.

Nuevo tipo mixto v2



Se agregaron tipos escalares en PHP 7. En PHP 7.1, tipos anulables. Y en PHP 8, tipos de unión. Ahora los programadores pueden especificar explícitamente tipos para variables, parámetros, clases, métodos y funciones, valores que devuelven métodos y funciones y propiedades de clase. Pero PHP no siempre admite tipos, esto se debe al hecho de que PHP es un lenguaje interpretado, es decir, PHP puede permitir que falte información sobre los tipos. Esto lleva al problema de que su significado es ambiguo cuando falta la información de tipo.
- la función no devuelve nada o es nula
- esperamos uno de varios tipos
- esperamos un tipo que no se pueda insinuar en PHP
Por estas razones, el tipo mixto fue inventado y agregado. El tipo mixto es uno de los siguientes tipos:
- matriz
bool
- invocable
- En t
- flotar
- nulo
- objeto
- recurso
- cuerda
Tenga en cuenta que mixto puede usarse como parámetro o tipo de propiedad, no solo como tipo de retorno. También tenga en cuenta que mixto ya incluye nulo, esto no puede hacerlo anulable. Lo siguiente arrojará un error:
// Fatal error: Mixed types cannot be nullable, null is already part of the mixed type.
function bar(): ?mixed {}


Lanzar expresiones



La cláusula de lanzamiento de PHP no puede lanzar excepciones en lugares donde solo se permiten expresiones, como funciones de flecha, operador de unión y operador ternario. PHP 8 convierte la instrucción throw en una expresión para hacer posibles estos casos.

// This was previously not possible since arrow functions only accept a single expression while throw was a statement.
$callable = fn() => throw new Exception();

// $value is non-nullable.
$value = $nullableValue ?? throw new InvalidArgumentException();

// $value is truthy.
$value = $falsableValue ?: throw new InvalidArgumentException();

// $value is only set if the array is not empty.
$value = !empty($array)
? reset($array)
: throw new InvalidArgumentException();


Hay otros lugares donde se puede usar que son más controvertidos. Estos casos están permitidos en PHP 8
$condition && throw new Exception();
$condition || throw new Exception();
$condition and throw new Exception();
$condition or throw new Exception();


Herencia de método privado



Anteriormente, PHP usaba los mismos métodos de verificación de herencia para métodos públicos, protegidos y privados. Es decir, los métodos privados se verificaron como protegidos y públicos. Y los métodos privados no estarán disponibles para las clases infantiles.
En PHP 8, esta verificación ya no se realiza para métodos privados. Además, usar una función privada final tampoco tiene sentido, ya que esto causará un error:

Warning: Private methods cannot be final as they are never overridden by other classes


Mapas débiles - Mapas débiles



WeakMap apareció en PHP 7.4 como la primera implementación, y en PHP 8 WeakMap amplía su implementación para que los mapas débiles contengan referencias de objetos que no impidan que los objetos se recojan basura.

Por ejemplo, los ORM, a menudo implementan cachés que contienen referencias a clases de entidad para mejorar el rendimiento de las relaciones entre entidades. Estos objetos no se pueden "recolectar basura" siempre que haya una referencia a ellos en la memoria caché.

Una gran ventaja de las cartas débiles es la capacidad de utilizar formas más amigables con los recursos para trabajar con estos objetos. Así son las cartas débiles:

class Foo 
{
private WeakMap $cache;

public function getSomethingWithCaching(object $obj): object
{
return $this->cache[$obj]
??= $this->computeSomethingExpensive($obj);
}
}


Usando ::class en objetos



Una nueva característica pequeña pero útil. Ahora en PHP 8 puede usar :: class en objetos, el resultado será idéntico a get_class ():
//antes
$bar = new Foo();
echo Foo::class;
//o
echo get_class($bar);
//'Foo'

//ahora será posible así
$foo = new Foo();
echo $foo::class;
//'Foo'


Excepción no capturada



Anteriormente, cada vez que usaba una excepción antes de PHP 8, tenía que especificar la variable si la estaba usando o no. Ahora puede saltear esta variable.
Fue así:
try {
//Algo esta mal
} catch (MySpecialException $exception) {
Log::error("Algo salió mal");
}


Y ahora se ha vuelto así:
try {
// Algo esta mal
} catch (MySpecialException) {
Log::error("Algo salió mal");
}


Tenga en cuenta que se debe especificar el tipo, no puede utilizar una captura vacía. Para capturar todas las excepciones y errores, puede usar su Throwable como un tipo de captura.

Coma final en listas de parámetros



Ahora puede dejar una coma al final cuando enumere los parámetros separados por comas y no habrá ningún error)
Puedes hacer lo siguiente:
public function(
string $parameterA,
int $parameterB,
Foo $objectfoo,
) {
// …
}


Hacer objetos DateTime desde la interfaz

Es posible hacer un objeto DateTime a partir de un objeto DateTimeImmutable utilizando DateTime :: createFromImmutable ($ immutableDateTime), pero lo contrario fue complicado. Agregar DateTime :: createFromInterface () y DatetimeImmutable :: createFromInterface () ahora permite que los objetos DateTime y DateTimeImmutable se conviertan entre sí.

DateTime::createFromInterface(DateTimeInterface $other);
DateTimeImmutable::createFromInterface(DateTimeInterface $other);


Nueva interfaz de cadena



La nueva interfaz Stringable se agrega automáticamente a las clases. Implementa el método mágico _toString () y no es necesario implementarlo manualmente.
Esto tiene dos propósitos:
- permitir el uso, string | Stringable para expresar string | object-with -__ toString ()
- Proporcione una ruta de actualización directa de PHP 7 a PHP 8

class Foo
{
public function __toString(): string
{
return 'foo';
}
}

function bar(Stringable $stringable) { /* … */ }

bar(new Foo());
bar('abc');


Nueva función str_contains ()



Esta función vino en ayuda de la conocida función strpos (). str_contains () comprueba si una cadena está contenida en otra cadena y devuelve un valor booleano (verdadero / falso) independientemente de si se encontró la cadena.

Fue así:
if (strpos('string with lots of words', 'words') !== false) { /* … */ }


Se hizo así:
if (str_contains('string with lots of words', 'words')) { /* … */ }


Nuevas funciones str_starts_with () y str_ends_with ()



str_starts_with () comprueba si una cadena comienza en otra línea y devuelve un valor booleano (verdadero / falso).

str_ends_with () comprueba lógicamente si una cadena termina con otra cadena y devuelve un valor booleano (verdadero / falso).

str_starts_with('haystack', 'hay'); // true
str_ends_with('haystack', 'stack'); // true


Anteriormente, esta funcionalidad se lograba utilizando las funciones existentes: substr, strpos / strrpos, strncmp o substr_compare (combinado con strlen). Curiosamente, la funcionalidad de str_starts_with y str_ends_with es tan necesaria que muchos marcos PHP principales lo admiten, incluidos Symfony, Laravel, Yii, FuelPHP y Phalcon.

Nueva función fdiv



Al usar la función fdiv ya no obtenemos errores al dividir por 0. Y obtenemos INF, -INF o NAN, según corresponda. La función fdiv realiza un tipo de función similar a las funciones fmod e intdiv.

Nueva funciónp get_resource_id ()



Los recursos son variables especiales en PHP que se refieren a recursos externos. Por ejemplo, conexión MySQL o descriptor de archivo.

A cada uno de estos recursos se le asigna una ID, aunque anteriormente la única forma de saber qué es una ID es convertir el recurso a int:

$resourceId = (int) $resource;


PHP 8 agrega la función get_resource_id (), haciendo que esta operación sea más obvia y escriba segura:

$resourceId = get_resource_id($resource);


El operador @ ya no "detiene" los errores fatales



Es posible que este cambio revele errores que se ocultaron nuevamente antes de PHP 8. ¡Asegúrese de configurar display_errors = Off en sus servidores de producción!

Nivel de mensaje de error predeterminado



Ahora, de manera predeterminada en error_reporting, el nivel de error se establecerá en E_ALL en lugar del E_ALL & ~ E_NOTICE & ~ E_STRICT & ~ E_DEPRECATED actual. Esto significa que pueden aparecer muchos errores que previamente se ignoraron en silencio, aunque es posible que ya hayan existido antes de PHP 8.

Métodos abstractos para mejorar los rasgos



Los rasgos pueden definir métodos abstractos que deben ser implementados por las clases que los usan. Sin embargo, hay una advertencia: antes de PHP 8, la firma de estas implementaciones de métodos no se verificó. Lo siguiente fue válido:

trait Test {
abstract public function test(int $input): int;
}

class UsesTrait
{
use Test;

public function test($input)
{
return $input;
}
}


PHP 8 realizará la validación correcta de la firma del método cuando use la propiedad e implemente sus métodos abstractos. Esto significa que necesitas escribir esto:

class UsesTrait
{
use Test;

public function test(int $input): int
{
return $input;
}
}


Precedencia de concatenación

Aunque este cambio ya estaba en desuso en PHP 7.4, este cambio ahora tiene efecto. Si escribiste algo como esto:

echo "sum: " . $a + $b;


PHP lo interpretaría previamente así:
echo ("sum: " . $a) + $b;



PHP 8 lo hará interpretar así:

echo "sum: " . ($a + $b);


Comprobación de tipo más estricto para operadores aritméticos y bit a bit

Antes de PHP 8, era posible aplicar operadores aritméticos o de bits a matrices, recursos u objetos. Esto ya no es posible y arrojará un TypeError:

[] % [42];
$object + 4;