1PHP 8.4 UPGRADE NOTES 2 31. Backward Incompatible Changes 42. New Features 53. Changes in SAPI modules 64. Deprecated Functionality 75. Changed Functions 86. New Functions 97. New Classes and Interfaces 108. Removed Extensions and SAPIs 119. Other Changes to Extensions 1210. New Global Constants 1311. Changes to INI File Handling 1412. Windows Support 1513. Other Changes 1614. Performance Improvements 17 18======================================== 191. Backward Incompatible Changes 20======================================== 21 22- CLI: 23 . The builtin server looks for an index file recursively by traversing parent 24 directories in case the specified file cannot be located. This process was 25 previously skipped if the path looked like it was referring to a file, i.e. 26 if the last path component contained a period. In that case, a 404 error was 27 returned. The behavior has been changed to look for an index file in all 28 cases. 29 30- Core: 31 . The type of PHP_DEBUG and PHP_ZTS constants changed to bool. 32 33- DOM: 34 . New methods and constants were added to some DOM classes. If you inherit 35 from these and you happen to have a method or property with the same name, 36 you might encounter errors if the declaration is incompatible. 37 Consult sections 2. New Features and 6. New Functions for a list of 38 newly implemented methods and constants. 39 . Some DOM methods previously returned false or a PHP_ERR DOMException if a new 40 node could not be allocated. They consistently throw an INVALID_STATE_ERR 41 DOMException now. This situation is extremely unlikely though and probably 42 will not affect you. As a result DOMImplementation::createDocument() now has 43 a tentative return type of DOMDocument instead of DOMDocument|false. 44 45- MBString: 46 . mb_encode_numericentity() and mb_decode_numericentity() now check that 47 the $map is only composed of integers, if not a ValueError is thrown. 48 . mb_http_input() now always throws a ValueError if the $type is invalid. 49 . On invalid strings (those with encoding errors), mb_substr() now interprets 50 character indices in the same manner as most other mbstring functions. This 51 means that character indices returned by mb_strpos() can be passed to mb_substr(). 52 . For SJIS-Mac (MacJapanese) strings, character indices passed to mb_substr() now 53 refer to the indices of the Unicode codepoints which are produced when the string 54 is converted to Unicode. This is significant because around 40 SJIS-Mac characters 55 convert to a sequence of multiple Unicode codepoints. 56 57- Opcache: 58 . The JIT config defaults changed from opcache.jit=tracing and 59 opcache.jit_buffer_size=0 to opcache.jit=disable and 60 opcache.jit_buffer_size=64M, respectively. This does not affect the default 61 behavior, the JIT is still disabled by default. However, it is now disabled 62 through the opcache.jit setting, rather than opcache.jit_buffer_size. This 63 may affect users who previously enabled JIT through opcache.jit_buffer_size 64 exclusively, without also specifying a JIT mode using opcache.jit. To enable 65 JIT, set the opcache.jit config value accordingly. 66 67- PDO_DBLIB: 68 . setAttribute, DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER and DBLIB_ATTR_DATETIME_CONVERT 69 have been changed to set value as a bool. 70 71- PDO_FIREBIRD: 72 . getAttribute, ATTR_AUTOCOMMIT has been changed to get the value as a bool. 73 74- PDO_MYSQL: 75 . getAttribute, ATTR_AUTOCOMMIT, ATTR_EMULATE_PREPARES, MYSQL_ATTR_DIRECT_QUERY have 76 been changed to get values as bool. 77 78- PDO_PGSQL: 79 . The DSN's credentials, when set, are given priority over their PDO 80 constructor counterparts, being closer to the documentation states. 81 82- PCNTL: 83 . The functions pcntl_sigprocmask(), pcntl_sigwaitinfo() and 84 pcntl_sigtimedwait() now throw: 85 - A ValueError if the $signals array is empty (except for 86 pcntl_sigprocmask() if the $mode is SIG_SETMASK). 87 - A TypeError if a value of the $signals array is not an integer 88 - A ValueError if a value of the $signals array is not a valid signal number 89 Moreover, those functions now always return false on failure. 90 In some case previously it could return the value -1. 91 . The function pcntl_sigprocmask() will also now throw: 92 - A ValueError if $mode is not one of SIG_BLOCK, SIG_UNBLOCK, or SIG_SETMASK 93 . The function pcntl_sigtimedwait() will also now throw: 94 - A ValueError if $seconds is less than 0 95 - A ValueError if $nanoseconds is less than 0 or greater than 1e9 96 - A ValueError if both $seconds and $nanoseconds are 0 97 98- SimpleXML: 99 . Get methods called, or casting to a string on a SimpleXMLElement will no 100 longer implicitly reset the iterator data, unless explicitly rewound. 101 For example, casting an element to a string within a foreach loop would 102 cause an infinite loop because it destroyed the current iterator data. 103 This is no longer the case as a consequence of the bugfixes for GH-12192, 104 GH-12208, #55098. 105 . Calling simplexml_import_dom() with a non-XML object now throws a TypeError 106 instead of a ValueError. 107 108- SPL: 109 . Out of bounds accesses in SplFixedArray now throw an exception of type 110 OutOfBoundsException instead of RuntimeException. As OutOfBoundsException 111 is a child class of RuntimeException, code that uses RuntimeException 112 continues to function. 113 114- Standard: 115 . round() now validates the value of the $mode parameter and throws a ValueError 116 for invalid modes. Previously invalid modes would have been interpreted as 117 PHP_ROUND_HALF_UP. 118 . strcspn() with empty $characters now returns the length of the string instead 119 of incorrectly stopping at the first NUL character. See GH-12592. 120 121- XML: 122 . The xml_set_*_handler() functions now declare and check for an effective 123 signature of callable|string|null for the $handler parameters. 124 Moreover, values of type string that correspond to method names, 125 of object set with xml_set_object() are now checked to see if the method 126 exists on the class of the previously passed object. 127 This means that xml_set_object() must now always be called prior to setting 128 method names as callables. 129 Passing an empty string to disable the handler is still allowed, 130 but not recommended. 131 132- XSL: 133 . XSLTProcessor::setParameter() will now throw a ValueError when its arguments 134 contain null bytes. This never actually worked correctly in the first place, 135 which is why it throws an exception nowadays. 136 . Failure to call a PHP function callback during evaluation now throws 137 instead of emitting a warning. 138 RFC: https://wiki.php.net/rfc/improve_callbacks_dom_and_xsl 139 . Calling XSLTProcessor::importStyleSheet() with a non-XML object now throws 140 a TypeError instead of a ValueError. 141 142======================================== 1432. New Features 144======================================== 145 146- Core: 147 . Added request_parse_body() function that allows parsing RFC1867 (multipart) 148 requests in non-POST HTTP requests. 149 RFC: https://wiki.php.net/rfc/rfc1867-non-post 150 151- Date: 152 . Added static methods 153 DateTime[Immutable]::createFromTimestamp(int|float $timestamp): static. 154 . Added method DateTime[Immutable]::getMicroseconds(): int. 155 . Added method 156 DateTime[Immutable]::setMicroseconds(int $microseconds): static. 157 158- DOM: 159 . Added constant DOMNode::DOCUMENT_POSITION_DISCONNECTED. 160 . Added constant DOMNode::DOCUMENT_POSITION_PRECEDING. 161 . Added constant DOMNode::DOCUMENT_POSITION_FOLLOWING. 162 . Added constant DOMNode::DOCUMENT_POSITION_CONTAINS. 163 . Added constant DOMNode::DOCUMENT_POSITION_CONTAINED_BY. 164 . Added constant DOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC. 165 . Implemented DOM HTML5 parsing and serialization. 166 RFC: https://wiki.php.net/rfc/domdocument_html5_parser. 167 This RFC adds the new DOM namespace along with class and constant aliases. 168 There are two new classes to handle HTML and XML documents: 169 DOM\HTMLDocument and DOM\XMLDocument. 170 These classes provide a cleaner API to handle HTML and XML documents. 171 Furthermore, the DOM\HTMLDocument class implements spec-compliant HTML5 172 parsing and serialization. 173 . It is now possible to pass any callable to registerPhpFunctions(). 174 RFC: https://wiki.php.net/rfc/improve_callbacks_dom_and_xsl 175 176- FPM: 177 . Flushing headers without a body will now succeed. See GH-12785. 178 179- Phar: 180 . Added support for the unix timestamp extension for zip archives. 181 182- PDO: 183 . Added support for driver-specific subclasses. 184 RFC: https://wiki.php.net/rfc/pdo_driver_specific_subclasses 185 This RFC adds subclasses for PDO in order to better support 186 database-specific functionalities. The new classes are 187 instantiatable either via calling the PDO::connect() method 188 or by invoking their constructor directly. 189 190- PDO_DBLIB: 191 . Fixed setAttribute and getAttribute (SakiTakamachi) 192 . Added PdoDbLib class (danack, kocsismate) 193 194- PDO_FIREBIRD: 195 . Added class PdoFirebird. 196 197- PDO_MYSQL: 198 . Added class PdoMysql. 199 200- PDO_ODBC: 201 . Added class PdoOdbc. 202 203- PDO_PGSQL: 204 . Added class PdoPgsql. 205 206- PDO_SQLITE: 207 . Added class PdoSqlite. 208 209- POSIX: 210 . Added constant POSIX_SC_CHILD_MAX 211 . Added constant POSIX_SC_CLK_TCK 212 213- Reflection: 214 . ReflectionAttribute now contains a $name property to improve the debugging 215 experience. 216 217- SOAP: 218 . Added support for clark notation for namespaces in class map. 219 It is now possible to specify entries in a class map with clark notation 220 to resolve a type with a specific namespace to a specific class. 221 For example: '{http://example.com}foo' => 'FooClass'. 222 . Instances of DateTimeInterface that are passed to xsd:datetime or similar 223 elements are now serialized as such instead of being serialized as an 224 empty string. 225 226- XSL: 227 . It is now possible to use parameters that contain both single and double 228 quotes. 229 . It is now possible to pass any callable to registerPhpFunctions(). 230 RFC: https://wiki.php.net/rfc/improve_callbacks_dom_and_xsl 231 232======================================== 2333. Changes in SAPI modules 234======================================== 235 236======================================== 2374. Deprecated Functionality 238======================================== 239 240- Curl: 241 . The CURLOPT_BINARYTRANSFER constant is deprecated. 242 243- Date: 244 . Calling DatePeriod::__construct(string $isostr, int $options = 0) is 245 deprecated. Use DatePeriod::createFromISO8601String() instead. 246 247- Intl: 248 . Calling intlcal_set() as well as calling IntlCalendar::set() with 249 more than 2 arguments is deprecated. Use either IntlCalendar::setDate() 250 or IntlCalendar::setDateTime() instead. 251 . Calling intlgregcal_create_instance() as well as calling 252 IntlGregorianCalendar::__construct() with more than 2 arguments is 253 deprecated. Use either IntlGregorianCalendar::createFromDate() or 254 IntlGregorianCalendar::createFromDateTime() instead. 255 256- LDAP: 257 . Calling ldap_connect() with more than 2 arguments is deprecated. Use 258 ldap_connect_wallet() instead. 259 . Calling ldap_exop() with more than 4 arguments is deprecated. Use 260 ldap_exop_sync() instead. 261 262- PgSQL: 263 . Calling pgsql_fetch_result() with 2 arguments is deprecated. Use the 264 3-parameter signature with a null $row parameter instead. 265 . Calling pg_field_prtlen() with 2 arguments is deprecated. Use the 266 3-parameter signature with a null $row parameter instead. 267 . Calling pg_field_is_null() with 2 arguments is deprecated. Use the 268 3-parameter signature with a null $row parameter instead. 269 270- Reflection: 271 . Calling ReflectionMethod::__construct() with 1 argument is deprecated. 272 Use ReflectionMethod::createFromMethodName() instead. 273 274- Session: 275 . Calling session_set_save_handler() with more than 2 arguments is 276 deprecated. Use the 2-parameter signature instead. 277 278- Standard: 279 . Calling stream_context_set_option() with 2 arguments is deprecated. 280 Use stream_context_set_options() instead. 281 282======================================== 2835. Changed Functions 284======================================== 285 286- Core: 287 . trigger_error() and user_error() now have a return type of true instead of 288 bool. 289 290- DOM: 291 . DOMDocument::registerNodeClass() now has a tentative return type of true. 292 Previously, the return type was bool but only true could be returned in practice. 293 294- Intl: 295 . IntlDateFormatter::__construct() throws a ValueError if the locale is invalid. 296 . NumberFormatter::__construct() throws a ValueError if the locale is invalid. 297 . NumberFormatter::ROUND_TOWARD_ZERO and NumberFormatter::ROUND_AWAY_FROM_ZERO 298 have been added as aliases for NumberFormatter::ROUND_DOWN and 299 NumberFormatter::ROUND_UP to be consistent with the new PHP_ROUND_* modes. 300 RFC: https://wiki.php.net/rfc/new_rounding_modes_to_round_function 301 . NumberFormatter::ROUND_HALFODD added to complement existing 302 NumberFormatter::ROUND_HALFEVEN functionality. 303 304- MBString: 305 . The behavior of mb_strcut is more consistent now on invalid UTF-8 and UTF-16 306 strings. (For valid UTF-8 and UTF-16 strings, there is no change.) 307 308- OpenSSL: 309 . The extra_attributes parameter in openssl_csr_new sets CSR attributes 310 instead of subject DN which was incorrectly done previously. 311 . The dn parameter in openssl_csr_new allows setting array of values for 312 a single entry. 313 . New serial_hex parameter added to openssl_csr_sign to allow setting serial 314 number in the hexadecimal format. 315 316- Output: 317 . Output handler status flags passed to the flags parameter of ob_start 318 are now cleared. 319 320- PDO: 321 . getAttribute, enabled to get the value of ATTR_STRINGIFY_FETCHES. 322 323- PDO_FIREBIRD: 324 . getAttribute, enabled to get values of FB_ATTR_DATE_FORMAT, FB_ATTR_TIME_FORMAT, 325 FB_ATTR_TIMESTAMP_FORMAT. 326 . Added new attributes to specify transaction isolation level and access mode. 327 Along with these, five constants (PDO::FB_TRANSACTION_ISOLATION_LEVEL, 328 PDO::FB_READ_COMMITTED, PDO::FB_REPEATABLE_READ, PDO::FB_SERIALIZABLE, 329 PDO::FB_WRITABLE_TRANSACTION) have been added. 330 . When using persistent connections, there is now a liveness check in the 331 constructor. 332 333- PDO_MYSQL: 334 . getAttribute, enabled to get the value of ATTR_FETCH_TABLE_NAMES. 335 336- PGSQL: 337 . pg_select, the conditions arguments accepts an empty array and is optional. 338 339- SPL: 340 . SplPriorityQueue::insert() and SplPriorityQueue::recoverFromCorruption() 341 now has a tentative return type of true 342 . SplHeap::insert() and SplHeap::recoverFromCorruption() 343 now has a tentative return type of true instead of bool 344 345- Standard: 346 . The internal implementation for rounding to integers has been rewritten 347 to be easier to verify for correctness and to be easier to maintain. 348 Some rounding bugs have been fixed as a result of the rewrite. For 349 example previously rounding 0.49999999999999994 to the nearest integer 350 would have resulted in 1.0 instead of the correct result 0.0. Additional 351 inputs might also be affected and result in different outputs compared to 352 earlier PHP versions. 353 . The default value of the 'cost' option for PASSWORD_BCRYPT for password_hash() 354 has been increased from '10' to '12'. 355 356 RFC: https://wiki.php.net/rfc/bcrypt_cost_2023 357 . Four new modes have been added to the round() function: PHP_ROUND_CEILING, 358 PHP_ROUND_FLOOR, PHP_ROUND_TOWARD_ZERO, PHP_ROUND_AWAY_FROM_ZERO. 359 360 RFC: https://wiki.php.net/rfc/new_rounding_modes_to_round_function 361 . debug_zval_dump() now indicates whether an array is packed. 362 . Fixed a bug caused by "pre-rounding" of the round() function. Previously, using 363 "pre-rounding" to treat a value like 0.285 (actually 0.28499999999999998) as a 364 decimal number and round it to 0.29. However, "pre-rounding" incorrectly rounds 365 certain numbers, so this fix removes "pre-rounding" and changes the way numbers 366 are compared, so that the values are correctly rounded as decimal numbers. 367 368======================================== 3696. New Functions 370======================================== 371 372- DOM: 373 . Added DOMNode::compareDocumentPosition(). 374 . Added DOMXPath::registerPhpFunctionNS(). 375 RFC: https://wiki.php.net/rfc/improve_callbacks_dom_and_xsl 376 377- MBString: 378 . Added mb_trim, mb_ltrim and mb_rtrim functions. 379 RFC: https://wiki.php.net/rfc/mb_trim 380 381- Opcache: 382 . If JIT is enabled, PHP will now exit with a fatal error on startup in case 383 of JIT startup initialization issues. 384 385- Sodium: 386 . Added the sodium_crypto_aead_aegis128l_*() and sodium_crypto_aead_aegis256l_*() 387 functions to support the AEGIS family of authenticated encryption algorithms, 388 that was introduced in libsodium 1.0.19. 389 . sodium_crypto_aead_aes256gcm_*() functions are now enabled on aarch64 CPUs 390 with the ARM cryptographic extensions. 391 392- XSL: 393 . Added XSLTProcessor::registerPhpFunctionNS(). 394 RFC: https://wiki.php.net/rfc/improve_callbacks_dom_and_xsl 395 396======================================== 3977. New Classes and Interfaces 398======================================== 399 400======================================== 4018. Removed Extensions and SAPIs 402======================================== 403 404- IMAP: 405 . The IMAP extension has been unbundled and moved to PECL. 406 RFC: https://wiki.php.net/rfc/unbundle_imap_pspell_oci8 407 408- PSpell: 409 . The pspell extension has been unbundled and moved to PECL. 410 RFC: https://wiki.php.net/rfc/unbundle_imap_pspell_oci8 411 412======================================== 4139. Other Changes to Extensions 414======================================== 415 416- Curl: 417 . The Curl extension now requires at least libcurl 7.61.0. 418 419- Intl: 420 . The class constants are typed now. 421 422- PDO: 423 . The class constants are typed now. 424 425- Reflection: 426 . The class constants are typed now. 427 428- Spl: 429 . The class constants are typed now. 430 431- Sqlite: 432 . The class constants are typed now. 433 434- XSL: 435 . The typed properties XSLTProcessor::$cloneDocument and 436 XSLTProcessor::$doXInclude are now declared. 437 438======================================== 43910. New Global Constants 440======================================== 441 442- Core: 443 . PHP_OUTPUT_HANDLER_PROCESSED. 444 445- Intl: 446 . The IntlDateFormatter class exposes now the new PATTERN constant 447 reflecting udat api's UDAT_PATTERN. 448 449- OpenSSL: 450 . X509_PURPOSE_OCSP_HELPER. 451 . X509_PURPOSE_TIMESTAMP_SIGN. 452 453- Standard: 454 . PHP_ROUND_CEILING. 455 . PHP_ROUND_FLOOR. 456 . PHP_ROUND_TOWARD_ZERO. 457 . PHP_ROUND_AWAY_FROM_ZERO. 458 459- Sockets: 460 . SO_EXCLUSIVEADDRUSE (Windows only). 461 462- XML: 463 . Added XML_OPTION_PARSE_HUGE to allow large inputs in xml_parse and 464 xml_parse_into_struct. 465 RFC: https://wiki.php.net/rfc/xml_option_parse_huge. 466 467======================================== 46811. Changes to INI File Handling 469======================================== 470 471======================================== 47212. Windows Support 473======================================== 474 475======================================== 47613. Other Changes 477======================================== 478 479======================================== 48014. Performance Improvements 481======================================== 482 483* The performance of DOMNode::C14N() is greatly improved for the case without 484 an xpath query. This can give a time improvement of easily two order of 485 magnitude for documents with tens of thousands of nodes. 486 487* The performance of strspn() and strcspn() is greatly improved. 488 They now run in linear time instead of being bounded by quadratic time. 489 490* mb_strcut() is much faster now for UTF-8 and UTF-16 strings. 491 492* Looking up mbstring encoding names is much faster now. 493 494* The performance of converting SJIS-win to unicode is greatly improved. 495 496* get_browser() is much faster now, up to 1.5x - 2.5x for some test cases. 497