Deprecations for PHP 7.2
Published on by Eric L. Barnes
The PHP 7.2 RFC for deprecating some current functionality has been approved. The following items are included in this list and will begin throwing deprecated notices:
__autoload
The magic __autoload function has been superseded by spl_autoload_register in PHP 5.1 and its use discouraged in the documentation. One primary advantage of spl_autoload_register() is the ability to provide multiple chained autoloaders, thus easing library interoperability. Both mechanism are mutually exclusive, i.e. code using __autoload() cannot interoperate with code using spl_autoload_register(). As the latter is much more commonly used and also employed by Composer, the __autoload() mechanism has only very limited applicability nowadays.
$php_errormsg
The $php_errormsg variable is created in the local scope whenever a non-fatal error is thrown if the track_errors ini setting is enabled (disabled by default) and the error has not been consumed by an error handler.
Apart from being ini-dependent language behavior, this behavior is highly magic and the error_get_last function provides a cleaner way of retrieving the last error. Since PHP 7 additionally the error_clear_last function is available, thus covering the last possible use-cases for $php_errormsg without magic scope manipulation.
create_function()
create_function() is a thin wrapper around the eval() language construct, allowing the creation of a function with a generated function name and the argument list and body code provided as string arguments. Before the introduction of closures in PHP 5.3 it provided a way to create something akin to lambda functions.
Due to the nature of its operation create_function(), apart from being a potential source of security issues, has very bad performance and memory usage characteristics and the use of real closures is in every way preferable.
mbstring.func_overload
The mbstring.func_overload ini setting allows replacing a certain subset of string functions with analogs from the mbstring extension. For example strlen() will no longer return the length of a string in bytes, instead it will return the length in code points according to the currently selected internal encoding.
This implies that code using mbstring.func_overload is incompatible with practically all other code, which is written under the assumption that basic string operations work normally. Some libraries outright forbid func_overload (e.g. Symfony), others will break in more subtle ways. Code that wants to support func_overload needs to conditionally switch between ordinary string functions and mbstring functions with 8bit encoding (however only cryptography libraries normally bother to do this).
(unset) cast
The (unset) cast casts a value to null. This means that (unset) expr is simply an expression that always returns null and has no other side effects. Apart from being useless, this behavior is also confusing, as many people reasonably assume that (unset) $a will behave similarly to unset($a), while in truth it does no such thing.
parse_str() without second argument
The parse_str() function is used to parse a query string either into an array if the second argument is used, or into the local symbol table if it is not used.
The second behavior is a remnant from the dark age of register_globals. It suffers from many of the same problems and presents a major security hazard if used on user-provided data.
gmp_random()
The gmp_random() function returns a random GMP number between 0 and 2**($n*BITS_PER_LIMB)-1, where $n is the function argument and BITS_PER_LIMB is a platform-specific parameter of the GMP/MPIR implementation that is not exposed to userland. As such, use of this function requires guessing the limb size and will likely have a platform dependence.
To remedy this PHP 5.6 introduced the gmp_random_bits() and gmp_random_range() functions, which allow precise control of the used random number range. These functions should always be preferred over gmp_random().
each()
The each() function can be used to iterate over an array, similarly to using foreach. On each call, it returns an array with the current key and value and advances the internal array pointer to the next position. The typical usage, as presented in the manual, is as follows:
reset($array);while (list($key, $val) = each($array)) { echo "$key => $val\n";}
The each()
function is inferior to foreach
, including being more than 10 times slower.
assert() with string argument
The assert() function has two modes of operation: If it is passed something other than a string, it will assert that the value is truthy. If a string is passed, it will be run through eval() and assert will check that the result of the eval() is truthy.
The reason for this behavior is that prior to PHP 7 this was the only way to prevent the assertion expression from evaluating. As of PHP 7, the zend.assertions ini option can be used to avoid evaluation of assertion expressions. As such, there is no longer a need for supporting implicitly evaluated string arguments.
This behavior of assert() makes it easy to introduce subtle remote code execution vulnerabilities. Using assert($value) to check if a value is truthy opens an RCE vulnerability if there is any chance for $value to be a string.
$errcontext argument of error handler
Error handlers set with set_error_handler() are passed an $errcontext as the last argument. This argument is an array containing all local variables at the point the error was generated.
This functionality is problematic for optimization because the $errcontext can be used to modify all references and objects in the current scope. As far as I am aware, this functionality is barely used and the trade-off here is not worthwhile. If people wish to inspect the variable-state at the point of an error, they should use a proper debugger.
Note that the error context only contains the local variables at the error site. The error backtrace, including $this and function arguments, will of course, stay available through debug_backtrace().
The RFC includes all the details on these changes as well as the votes casts.
Eric is the creator of Laravel News and has been covering Laravel since 2012.