From 498a9608a56c93647c3f9a259d42d683727c5afa Mon Sep 17 00:00:00 2001 From: Theodore Brown Date: Fri, 14 Nov 2025 10:32:45 -0600 Subject: [PATCH 1/3] Revert to simpler `array_last()` example The Stopwatch implementation details tend to obfuscate the benefit of `array_last()`. This is the simplest new feature in PHP 8.5, and it doesn't make sense to give it the most complicated example. --- releases/8.5/release.inc | 58 +++------------------------------------- 1 file changed, 4 insertions(+), 54 deletions(-) diff --git a/releases/8.5/release.inc b/releases/8.5/release.inc index 246c654a33..9d7c657ced 100644 --- a/releases/8.5/release.inc +++ b/releases/8.5/release.inc @@ -254,34 +254,9 @@ PHP
start = hrtime(true); - } - - public function stopLap() - { - $fromStart = hrtime(true) - $this->start; - $lastLap = $this->laps !== [] - ? $this->laps[array_key_last($this->laps)] - : 0; - $lapDuration = $fromStart - $lastLap; - - $this->laps[] = $fromStart; - - return $lapDuration; - } -} - -$watch = new Stopwatch(); -for ($i = 1; $i < 5; $i++) { - printf("Lap #%d took %dns\n", $i, $watch->stopLap()); -} +$lastEvent = $events === [] + ? null + : $events[array_key_last($events)]; PHP ); ?> @@ -293,32 +268,7 @@ PHP
start = hrtime(true); - } - - public function stopLap() - { - $fromStart = hrtime(true) - $this->start; - $lastLap = array_last($this->laps) ?? 0; - $lapDuration = $fromStart - $lastLap; - - $this->laps[] = $fromStart; - - return $lapDuration; - } -} - -$watch = new Stopwatch(); -for ($i = 1; $i < 5; $i++) { - printf("Lap #%d took %dns\n", $i, $watch->stopLap()); -} +$lastEvent = array_last($events); PHP ); ?>
From f1dd67797e71e62ab8b9d6b283d118229295333b Mon Sep 17 00:00:00 2001 From: Theodore Brown Date: Fri, 14 Nov 2025 12:12:02 -0600 Subject: [PATCH 2/3] Update deprecations and BC breaks The deprecation for returning a non-string from a user output handler was reverted. Also documented the warning for destructuring non-array values. --- releases/8.5/release.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/8.5/release.inc b/releases/8.5/release.inc index 9d7c657ced..4c9b86f13e 100644 --- a/releases/8.5/release.inc +++ b/releases/8.5/release.inc @@ -414,12 +414,12 @@ PHP
  • The backtick operator as an alias for shell_exec() has been deprecated.
  • Non-canonical cast names (boolean), (integer), (double), and (binary) have been deprecated. Use (bool), (int), (float), and (string) instead, respectively.
  • The disable_classes INI setting has been removed as it causes various engine assumptions to be broken.
  • -
  • Returning a non-string from a user output handler is deprecated.
  • Terminating case statements with a semicolon instead of a colon has been deprecated.
  • Using null as an array offset or when calling array_key_exists() is now deprecated. Use an empty string instead.
  • It is no longer possible to use "array" and "callable" as class alias names in class_alias().
  • The __sleep() and __wakeup() magic methods have been soft-deprecated. The __serialize() and __unserialize() magic methods should be used instead.
  • A warning is now emitted when casting NAN to other types.
  • +
  • Destructuring non-array values (other than null) using [] or list() now emits a warning.
  • A warning is now emitted when casting floats (or strings that look like floats) to int if they cannot be represented as one.
  • From faf239ec28e046450585a6dcee6212d627142944 Mon Sep 17 00:00:00 2001 From: Theodore Brown Date: Fri, 14 Nov 2025 13:48:03 -0600 Subject: [PATCH 3/3] Extract strings for translation This commit does not change any content. --- releases/8.5/common.php | 10 +++++-- releases/8.5/languages/en.php | 22 ++++++++++++++ releases/8.5/release.inc | 55 +++++++++++++++++++++-------------- 3 files changed, 63 insertions(+), 24 deletions(-) diff --git a/releases/8.5/common.php b/releases/8.5/common.php index ef05a2a1fb..f8796b6585 100644 --- a/releases/8.5/common.php +++ b/releases/8.5/common.php @@ -59,12 +59,18 @@ function language_chooser(string $currentLang): void { '; } -function message($code, $language = 'en') +function message($code, $language = 'en', array $interpolations = []) { $original = require __DIR__ . '/languages/en.php'; if (($language !== 'en') && file_exists(__DIR__ . '/languages/' . $language . '.php')) { $translation = require __DIR__ . '/languages/' . $language . '.php'; } - return $translation[$code] ?? $original[$code] ?? $code; + $message = $translation[$code] ?? $original[$code] ?? $code; + + foreach ($interpolations as $name => $value) { + $message = str_replace("{{$name}}", $value, $message); + } + + return $message; } diff --git a/releases/8.5/languages/en.php b/releases/8.5/languages/en.php index 9c58cdec5f..d216924a52 100644 --- a/releases/8.5/languages/en.php +++ b/releases/8.5/languages/en.php @@ -22,8 +22,30 @@ 'persistent_curl_share_handles_description' => 'Unlike curl_share_init(), handles created by curl_share_init_persistent() will not be destroyed at the end of the PHP request. If a persistent share handle with the same set of share options is found, it will be reused, avoiding the cost of initializing cURL handles each time.', 'new_classes_title' => 'Additional features and improvements', + 'fatal_error_backtrace' => 'Fatal Errors (such as an exceeded maximum execution time) now include a backtrace.', + 'const_attribute_target' => 'Attributes can now target constants.', + 'override_attr_properties' => '{0} attribute can now be applied to properties.', + 'deprecated_traits_constants' => '{0} attribute can be used on traits and constants.', + 'asymmetric_static_properties' => 'Static properties now support asymmetric visibility.', + 'final_promoted_properties' => 'Properties can be marked as final using constructor property promotion.', + 'closure_getCurrent' => 'Added Closure::getCurrent() method to simplify recursion in anonymous functions.', + 'partitioned_cookies' => 'setcookie() and setrawcookie() now support the "partitioned" key.', + 'get_set_error_handler' => 'New {0} and {1} functions are available.', + 'new_dom_element_methods' => 'New {0} and {1} methods are available.', + 'grapheme_levenshtein' => 'Added {0} function.', + 'delayed_target_validation' => 'New {0} attribute can be used to suppress compile-time errors from core and extension attributes that are used on invalid targets.', 'bc_title' => 'Deprecations and backward compatibility breaks', + 'bc_backtick_operator' => 'The backtick operator as an alias for {0} has been deprecated.', + 'bc_non_canonical_cast_names' => 'Non-canonical cast names (boolean), (integer), (double), and (binary) have been deprecated. Use (bool), (int), (float), and (string) instead, respectively.', + 'bc_disable_classes' => 'The {0} INI setting has been removed as it causes various engine assumptions to be broken.', + 'bc_semicolon_after_case' => 'Terminating case statements with a semicolon instead of a colon has been deprecated.', + 'bc_null_array_offset' => 'Using null as an array offset or when calling {0} is now deprecated. Use an empty string instead.', + 'bc_class_alias_names' => 'It is no longer possible to use "array" and "callable" as class alias names in {0}.', + 'bc_sleep_wakeup' => 'The {0} and {1} magic methods have been soft-deprecated. The {2} and {3} magic methods should be used instead.', + 'bc_casting_nan' => 'A warning is now emitted when casting {0} to other types.', + 'bc_non_array_destructuring' => 'Destructuring non-array values (other than null) using {0} or {1} now emits a warning.', + 'bc_casting_non_int_floats' => 'A warning is now emitted when casting floats (or strings that look like floats) to int if they cannot be represented as one.', 'footer_title' => 'Better syntax, improved performance and type safety.', 'footer_description' => '

    The full list of changes is recorded in the ChangeLog.

    diff --git a/releases/8.5/release.inc b/releases/8.5/release.inc index 4c9b86f13e..c845371ec4 100644 --- a/releases/8.5/release.inc +++ b/releases/8.5/release.inc @@ -391,18 +391,24 @@ PHP

      -
    • Fatal Errors (such as an exceeded maximum execution time) now include a backtrace.
    • -
    • Attributes can now target constants.
    • -
    • #[\Override] attribute can now be applied to properties.
    • -
    • #[\Deprecated] attribute can be used on traits and constants.
    • -
    • Static properties now support asymmetric visibility.
    • -
    • Properties can be marked as final using constructor property promotion.
    • -
    • Added Closure::getCurrent() method to simplify recursion in anonymous functions.
    • -
    • setcookie() and setrawcookie() now support the "partitioned" key.
    • -
    • New get_error_handler() and get_exception_handler() functions are available.
    • -
    • New Dom\Element::getElementsByClassName() and Dom\Element::insertAdjacentHTML() methods are available.
    • -
    • Added grapheme_levenshtein() function.
    • -
    • New #[\DelayedTargetValidation] attribute can be used to suppress compile-time errors from core and extension attributes that are used on invalid targets.
    • +
    • +
    • +
    • #[\Override]']) ?>
    • +
    • #[\Deprecated]']) ?>
    • +
    • +
    • +
    • +
    • +
    • get_error_handler()', + 'get_exception_handler()', + ]) ?>
    • +
    • Dom\Element::getElementsByClassName()', + 'Dom\Element::insertAdjacentHTML()', + ]) ?>
    • +
    • grapheme_levenshtein()']) ?>
    • +
    • #[\DelayedTargetValidation]']) ?>
    @@ -411,16 +417,21 @@ PHP

      -
    • The backtick operator as an alias for shell_exec() has been deprecated.
    • -
    • Non-canonical cast names (boolean), (integer), (double), and (binary) have been deprecated. Use (bool), (int), (float), and (string) instead, respectively.
    • -
    • The disable_classes INI setting has been removed as it causes various engine assumptions to be broken.
    • -
    • Terminating case statements with a semicolon instead of a colon has been deprecated.
    • -
    • Using null as an array offset or when calling array_key_exists() is now deprecated. Use an empty string instead.
    • -
    • It is no longer possible to use "array" and "callable" as class alias names in class_alias().
    • -
    • The __sleep() and __wakeup() magic methods have been soft-deprecated. The __serialize() and __unserialize() magic methods should be used instead.
    • -
    • A warning is now emitted when casting NAN to other types.
    • -
    • Destructuring non-array values (other than null) using [] or list() now emits a warning.
    • -
    • A warning is now emitted when casting floats (or strings that look like floats) to int if they cannot be represented as one.
    • +
    • shell_exec()']) ?>
    • +
    • +
    • disable_classes']) ?>
    • +
    • +
    • array_key_exists()']) ?>
    • +
    • class_alias()']) ?>
    • +
    • __sleep()', + '__wakeup()', + '__serialize()', + '__unserialize()', + ]) ?>
    • +
    • NAN']) ?>
    • +
    • []', 'list()']) ?>
    • +