rfc:deprecations_php_7_4

This is an old revision of the document!


PHP RFC: Deprecations for PHP 7.4

Introduction

The RFC proposes to deprecate the listed functionality in PHP 7.4 and remove it in PHP 8.

The following list provides a short overview of the functionality targeted for deprecation, while more detailed explanation is provided in the Proposal section:

  • enable_dl php.ini directive
  • The real type
  • The hebrev() & hebrevc() functions
  • Magic quotes legacy
  • array_key_exists() with objects
  • FILTER_SANITIZE_MAGIC_QUOTES filter
  • apache_request_headers() function
  • Reflection export() methods
  • mb_strrpos() with encoding as 3rd argument
  • is_writeable() function alias
  • implode() parameter order mix
  • convert_cyr_string() function
  • money_format() function
  • ezmlm_hash() function
  • allow_url_include ini directive
  • restore_include_path() function
  • Unbinding $this from non-static closures

Proposal

Each feature proposed for deprecation is voted separately and requires a 2/3 majority. All votes refer to deprecation in PHP 7.4 and removal in PHP 8.0.

enable_dl php.ini directive

The enable_dl php.ini directive controls whether or not the dl() function is available. However, as of PHP 7.0 the dl() function is already only available on the CLI, CGI and Embed SAPIs. As such, it is already not available in typical web server SAPIs (FPM and Apache), where dl() may be disabled for security reasons. (TODO: CGI is a server SAPI, even if it's a bad one.)

Additionally the dl() function can also be disabled using the normal disable_functions mechanism, as such there is no need to have a separate ini option just for it.

Proposal: If the CLI, CGI or Embed SAPIs are used, emit a deprecation warning if enable_dl is non zero at start-up. In PHP 8 the option is removed and availability of dl() functionality is controlled only the SAPI.

The 'real' type

Currently PHP has a float data type, with two additional aliases: double and real. The latter is very rarely used and should be deprecated. This includes both the (real) type-cast and the is_real() function. Currently the settype() function does not support the “real” string, so it is not affected.

Upgrading is relatively easy and can be done by replacing all (real) type-casts with (float) and all is_real() calls with is_float().

Proposal: Emit a deprecation warning each time the (real) type-cast is used and mark is_real() as deprecated.

The hebrev() and hebrevc() functions

The hebrev() and hebrevc() functions helped display Hebrew on websites by converting logical Hebrew text to visual representation. Since the introduction of proper Unicode bidi support, this is no longer necessary. See W3C Visual vs. logical ordering of text for more information. As said there: “You should always create HTML (and any other type of markup) using logical ordering, and never use visual.” The legacy hebrev() functions violate this principle.

The hebrevc() function is essentially the same as calling nl2br() on the result of a hebrev() call.

Proposal: Mark hebrev() or hebrevc() as deprecated.

Magic quotes legacy

PHP's infamous magic_quotes configuration was removed in PHP 5.4 and the function implementations of checking whether or not these settings have been enabled have returned false since then. With PHP 7.0 not having magic_quotes at all, it is time to deprecate these functions and remove them entirely.

Proposal: Mark get_magic_quotes_gpc() and get_magic_quotes_runtime() as deprecated. This should only impact legacy code bases prior to PHP 5.4, running non-supported versions of PHP.

array_key_exists() with objects

The documentation already marks the use of array_key_exists() with objects as legacy behavior:

For backward compatibility reasons, array_key_exists() will also return TRUE if key is a property defined within an object given as array. This behaviour should not be relied upon, and care should be taken to ensure that array is an array. To check whether a property exists in an object, use property_exists().

array_key_exists() on objects also has some technical issues: It operates directly on mangled property names and does not respect property visibility. Furthermore, it does not take into account differences in normalization between array and object keys, so incorrect results may be returned for properties with integral keys.

Additionally, the fact that array_key_exists() accepts objects may mistakenly lead users to believe that it can operate on ArrayAccess objects in a sensible manner. This is not the case: array_key_exists() has no support for ArrayAccess, it exclusively works on mangled object properties.

Proposal: Throw a deprecation warning if an object is passed to array_key_exists().

FILTER_SANITIZE_MAGIC_QUOTES

Magic quotes were deprecated all the way back in PHP 5.3 and later removed in PHP 5.4. The filter extension implements a sanitization filter that mimics this behavior of magic_quotes by calling addslashes() on the input in question.

In PHP 7.3 add_slashes (FILTER_SANITIZE_ADD_SLASHES) was added as a new alias for this filter, to allow us to move away from the magic_quotes terminology.

Proposed action: Emit a deprecation notice each time the FILTER_SANITIZE_MAGIC_QUOTES filter is used and advise users to use the add_slashes (FILTER_SANITIZE_ADD_SLASHES) filter instead.

apache_request_headers() function

This function with an Apache-specific name is also available in other SAPIs, even though it is also available under the SAPI-independent name getallheaders(). The SAPI-specific function should be removed in favor of the more general one.

Proposed action: Mark apache_request_headers() as deprecated.

Reflection export() methods

The Reflector interface, which is implemented by all reflection classes, specifies two methods: __toString() and export(). The latter is a static method which, ostensibly, does not accept arguments. In reality this static method is implemented with varying signatures in each subclass, something which would normally result in an incompatible signature error. However, the implementation uses an internal mechanism to suppress this error.

The export() methods are essentially equivalent to a combination of the class constructor and __toString(). For example:

ReflectionFunction::export('foo');
// same as
echo new ReflectionFunction('foo'), "\n";
 
$str = ReflectionFunction::export('foo', true);
// same as
$str = (string) new ReflectionFunction('foo');

As such, the export() method is wholly unnecessary, confusing, and violates PHP's own inheritance rules.

Proposed action: In PHP 7.4 remove the method from the Reflector interface and deprecate all implementations of the method in reflection classes. In PHP 8 also remove the implementations.

mb_strrpos() with encoding as 3rd argument

The documentation for mb_strrpos() states:

The encoding parameter was moved from the third position to the fourth in PHP 5.2.0. For backward compatibility, encoding can be specified as the third parameter, but doing so is deprecated and will be removed in the future.

However, this deprecation has never been realized in the implementation. The need to support both signatures makes this parameter behave subtly different from other integer parameters (e.g. it is not subject to strict types). As little software is expected to support both PHP 7.4 and PHP 5.1, enforcing the new signature does not pose a significant backwards compatibility concern.

Proposed action: In PHP 7.4 throw a deprecation warning if an encoding is passed as the 3rd argument. In PHP 8 change the argument to accept an integer only.

is_writeable()

The is_writeable() function is an alias of is_writable(). is_writeable() is notorious in the sense that it has a spelling mistake in its name and has been considered soft deprecated since the introduction of is_writable().

Proposal: Deprecate the alias is_writeable().

implode() parameter order mix

For historical reasons, the implode() function supports passing the $glue and $pieces parameters in reverse order from the documented order of arguments. This is inconsistent and makes the argument handling non-standard (for example, strict types are not respected). This also affects the alias join().

Proposal: Emit a deprecation warning when calling implode($pieces, $glue) or join($pieces, $glue). Calling the function with just an array continues to be allowed: implode($pieces) does not generate a deprecation warning.

convert_cyr_string()

The convert_cyr_string() function allows conversion between Cyrillic character sets. The character sets are specified using obscure single character names, such as convert_cyr_string($str, “k”, “i”). This is a legacy function from a time where PHP did not provide general functions for conversion between character sets. Nowadays one of mb_convert_encoding(), iconv() or UConverter may be used for this purpose.

Proposal: Mark convert_cyr_string() as deprecated.

money_format()

The money_format() function formats currency values using locale-specific settings. It is based on the strfmon() C function, which is not supported on all platforms. Most notably it is not available on Windows. Nowadays the NumberFormatter::formatCurrency() method provided by intl should be used instead, which is both platform-independent and does not rely on the system locale. Additionally, intl also provides the ability to parse currency values using NumberFormatter::parseCurrency().

Furthermore, the strfmon() implementation seems to have an internal buffer overrun on macos, which indicates that this functionality is not well tested.

Proposal: Mark money_format() as deprecated.

ezmlm_hash()

The ezmlm_hash() function creates hashes of email addresses which the EZMLM/QMail mailing list system understands. This function is of very limited usefulness for the average PHP developer as the EZMLM/QMail system is barely maintained and its last release was in 2007. The function was most likely originally added for use in the php.net mailing list infrastructure. It can be trivially reimplemented in userland code if needed.

Proposal: Mark ezmlm_hash() as deprecated.

allow_url_include

The allow_url_include ini directive (disabled by default) allows the require, require_once, include and include_once language constructs to use URL stream wrappers. To use this ini directive, the allow_url_fopen ini directive must also be enabled.

Enabling this option creates a potential security hazard if the path passed to one of the include constructs is crafted by external data. The ability to include a PHP file from a remote domain is questionable in the first place and has a huge potential security risk and therefore should be deprecated from PHP.

Proposal: Add a deprecation notice if allow_url_include=1 on startup.

restore_include_path() function

This function is essentially an “alias” of doing ini_restore('include_path'). The main rationale for this is to clean up the standard library for consistency, similar to what we have done with other functions that are just wrappers for ini directives.

Proposal: Mark restore_include_path() as deprecated.

Unbinding $this from non-static closures

Currently it is possible to unbind the $this variable from a closure that originally had one by using $closure->bindTo(null). Due to the removal of static calls to non-static methods in PHP 8, we now have a guarantee that $this always exists inside non-static methods. We would like to have a similar guarantee that $this always exists for non-static closures declared inside non-static methods. Otherwise, we will end up imposing an unnecessary performance penalty either on $this accesses in general, or $this accesses inside such closures.

Proposal: Deprecate unbinding $this from a closure that originally had a $this binding. In particular this applies to non-static closures declared inside non-static methods. A $this binding can be avoided in the first place by marking the closure as static.

Backward Incompatible Changes

For PHP 7.4 additional deprecation notices will appear. For PHP 8.0 the previously deprecated functionality will no longer be available.

rfc/deprecations_php_7_4.1562580818.txt.gz · Last modified: 2019/07/08 10:13 by nikic