PHP 8.3 es una actualización importante del lenguaje PHP.
Contiene muchas características nuevas, como la tipificación explícita de constantes de clase, la clonación profunda de propiedades de solo lectura y adiciones a la funcionalidad de aleatoriedad. Como siempre, también incluye mejoras de rendimiento, correcciones de errores y limpieza general.
interface I {
// We may naively assume that the PHP constant is always a string.
const PHP = 'PHP 8.2';
}
class Foo implements I {
// But implementing classes may define it as an array.
const PHP = [];
}interface I {
const string PHP = 'PHP 8.3';
}
class Foo implements I {
const string PHP = [];
}
// Fatal error: Cannot use array as value for class constant
// Foo::PHP of type stringclass Foo {
const PHP = 'PHP 8.2';
}
$searchableConstant = 'PHP';
var_dump(constant(Foo::class . "::{$searchableConstant}"));class Foo {
const PHP = 'PHP 8.3';
}
$searchableConstant = 'PHP';
var_dump(Foo::{$searchableConstant});#[\Override]Al agregar el atributo #[\Override] a un método, PHP asegurará que un método con el mismo nombre exista en una clase padre o en una interfaz implementada. Agregar el atributo aclara que la sobreescritura de un método padre es intencional y simplifica la refactorización, porque la eliminación de un método padre sobreescrito será detectada.
use PHPUnit\Framework\TestCase;
final class MyTest extends TestCase {
protected $logFile;
protected function setUp(): void {
$this->logFile = fopen('/tmp/logfile', 'w');
}
protected function taerDown(): void {
fclose($this->logFile);
unlink('/tmp/logfile');
}
}
// The log file will never be removed, because the
// method name was mistyped (taerDown vs tearDown).use PHPUnit\Framework\TestCase;
final class MyTest extends TestCase {
protected $logFile;
protected function setUp(): void {
$this->logFile = fopen('/tmp/logfile', 'w');
}
#[\Override]
protected function taerDown(): void {
fclose($this->logFile);
unlink('/tmp/logfile');
}
}
// Fatal error: MyTest::taerDown() has #[\Override] attribute,
// but no matching parent method existsreadonly las propiedades ahora pueden ser modificadas una vez dentro del método mágico __clone para permitir la clonación profunda de propiedades de solo lectura.
class PHP {
public string $version = '8.2';
}
readonly class Foo {
public function __construct(
public PHP $php
) {}
public function __clone(): void {
$this->php = clone $this->php;
}
}
$instance = new Foo(new PHP());
$cloned = clone $instance;
// Fatal error: Cannot modify readonly property Foo::$phpclass PHP {
public string $version = '8.2';
}
readonly class Foo {
public function __construct(
public PHP $php
) {}
public function __clone(): void {
$this->php = clone $this->php;
}
}
$instance = new Foo(new PHP());
$cloned = clone $instance;
$cloned->php->version = '8.3';json_validate()json_validate() permite verificar si una cadena es JSON sintácticamente válido, siendo más eficiente que json_decode().
function json_validate(string $string): bool {
json_decode($string);
return json_last_error() === JSON_ERROR_NONE;
}
var_dump(json_validate('{ "test": { "foo": "bar" } }')); // truevar_dump(json_validate('{ "test": { "foo": "bar" } }')); // trueRandomizer::getBytesFromString()La Extensión Aleatoria que se agregó en PHP 8.2 se extendió con un nuevo método para generar cadenas aleatorias compuestas solo por bytes específicos. Este método permite al desarrollador generar fácilmente identificadores aleatorios, como nombres de dominio y cadenas numéricas de longitud arbitraria.
// This function needs to be manually implemented.
function getBytesFromString(string $string, int $length) {
$stringLength = strlen($string);
$result = '';
for ($i = 0; $i < $length; $i++) {
// random_int is not seedable for testing, but secure.
$result .= $string[random_int(0, $stringLength - 1)];
}
return $result;
}
$randomDomain = sprintf(
"%s.example.com",
getBytesFromString(
'abcdefghijklmnopqrstuvwxyz0123456789',
16,
),
);
echo $randomDomain;// A \Random\Engine may be passed for seeding,
// the default is the secure engine.
$randomizer = new \Random\Randomizer();
$randomDomain = sprintf(
"%s.example.com",
$randomizer->getBytesFromString(
'abcdefghijklmnopqrstuvwxyz0123456789',
16,
),
);
echo $randomDomain;Randomizer::getFloat() y Randomizer::nextFloat()Debido a la precisión limitada y el redondeo implícito de los números de punto flotante, generar un flotante imparcial dentro de un intervalo específico no es trivial y las soluciones comunes de usuario pueden generar resultados sesgados o números fuera del rango solicitado.
La Aleatorizadora también se extendió con dos métodos para generar flotantes aleatorios de manera imparcial. El método Randomizer::getFloat() usa el algoritmo de sección γ que se publicó en Drawing Random Floating-Point Numbers from an Interval. Frédéric Goualard, ACM Trans. Model. Comput. Simul., 32:3, 2022.
// Returns a random float between $min and $max, both including.
function getFloat(float $min, float $max) {
// This algorithm is biased for specific inputs and may
// return values outside the given range. This is impossible
// to work around in userland.
$offset = random_int(0, PHP_INT_MAX) / PHP_INT_MAX;
return $offset * ($max - $min) + $min;
}
$temperature = getFloat(-89.2, 56.7);
$chanceForTrue = 0.1;
// getFloat(0, 1) might return the upper bound, i.e. 1,
// introducing a small bias.
$myBoolean = getFloat(0, 1) < $chanceForTrue;$randomizer = new \Random\Randomizer();
$temperature = $randomizer->getFloat(
-89.2,
56.7,
\Random\IntervalBoundary::ClosedClosed,
);
$chanceForTrue = 0.1;
// Randomizer::nextFloat() is equivalent to
// Randomizer::getFloat(0, 1, \Random\IntervalBoundary::ClosedOpen).
// The upper bound, i.e. 1, will not be returned.
$myBoolean = $randomizer->nextFloat() < $chanceForTrue;El linter de línea de comandos ahora acepta entrada variada para nombres de archivos a revisar
php -l foo.php bar.php
No syntax errors detected in foo.php
php -l foo.php bar.php
No syntax errors detected in foo.php
No syntax errors detected in bar.php
DOMElement::getAttributeNames(), DOMElement::insertAdjacentElement(), DOMElement::insertAdjacentText(), DOMElement::toggleAttribute(), DOMNode::contains(), DOMNode::getRootNode(), DOMNode::isEqualNode(), DOMNameSpaceNode::contains(), y DOMParentNode::replaceChildren().IntlCalendar::setDate(), IntlCalendar::setDateTime(), IntlGregorianCalendar::createFromDate(), y IntlGregorianCalendar::createFromDateTime().ldap_connect_wallet() y ldap_exop_sync().mb_str_pad().posix_sysconf(), posix_pathconf(), posix_fpathconf(), y posix_eaccess().ReflectionMethod::createFromMethodName().socket_atmark().str_increment(), str_decrement(), y stream_context_set_options().ZipArchive::getArchiveFlag().zend.max_allowed_stack_size para establecer el tamaño máximo permitido de la pila.n a un arreglo vacío ahora asegurará que el siguiente índice sea n + 1 en lugar de 0.range().U_MULTIPLE_DECIMAL_SEPERATORS está obsoleta en favor de U_MULTIPLE_DECIMAL_SEPARATORS.MT_RAND_PHP Mt19937 está obsoleta.ReflectionClass::getStaticProperties() ya no es nulo.assert.active, assert.bail, assert.callback, assert.exception, y assert.warning han sido obsoletas.get_class() y get_parent_class() sin argumentos está obsoleto.