PHP RFC: Deprecate remains of string evaluated code assertions
- Version: 0.9
- Date: 2023-05-31
- Author: George Peter Banyard, girgias@php.net
- Status: Implemented: https://github.com/php/php-src/commit/3d4ff5ae22e73a3f4c41a26c0d2eb11646ecdd88
- Target Version: PHP 8.3
- First Published at: https://wiki.php.net/rfc/assert-string-eval-cleanup
Introduction
Prior to PHP 7 assertions via the assert function could only operate on boolean values or with strings, in which case the string was evaluated and the result of it would be interpreted. The behaviour used by assert()
is dependent on various INI settings that can also be set using the assert_options()
function.
PHP 7 introduced “Expectations” which work with arbitrary expressions without needing to use eval()
internally by utilizing the newly introduced AST. To preserve backwards compatibility, none of the previous assert INI settings were removed to allow the usage of “legacy” code assertions while migrating to the expression based one. In doing so, 2 new INI settings were introduced, zend_assertions
and assert.exception
.
Moreover, the “legacy” code assertions were deprecated in PHP 7.2 and have been removed in PHP 8.0. However, only the assert.quiet_eval
INI setting and corresponding ASSERT_QUIET_EVAL
have been removed. None of the other INI settings related to those assertions had been deprecated nor removed. Moreover, with the removal of the code assertions in PHP 8.0 some subtle behavioural changes were made if one continues to use the legacy INI settings.
Thus, the proposal is to deprecate those INI settings, the assert_options()
function that allows to set them, and the relevant ASSERT_*
constants.
The INI settings and constants in question are:
assert.active
andASSERT_ACTIVE
assert.warning
andASSERT_WARNING
assert.bail
andASSERT_BAIL
assert.callback
andASSERT_CALLBACK
assert.exception
andASSERT_EXCEPTION
which were introduced in PHP 7.0
We will now explain what each of these settings does:
assert.active
Enabled by default. If disabled, any call to the assert()
function will immediately return true
.
Otherwise, the assertion is executed.
assert.warning
Enabled by default. If enabled, a warning is emitted if an assertion fails.
As of PHP 7, this setting only has an effect if assert.exception
is disabled.
assert.bail
Disabled by default. If enabled, the engine bails out when an assertion fails. One needs to remember that prior to PHP 7, the engine didn't throw exceptions and thus this was the only way to abort execution on assertion failure.
assert.callback
null
by default. This setting allows defining a function (as a string) that should be called when an assertion fails.
The only way to assign a more generic callable (e.g. an object having an __invoke()
magic method) is by using the assert_options()
function.
assert.exception
Enabled by default. If enabled, an AssertionError
or a custom exception is thrown if an assertion fails.
Behavioural changes between PHP 7 and 8
With the removal of the string evaluated assertion in PHP, some unintended behavioural changes were made.
Providing a custom exception short-circuits assert()
As of PHP 8.0, if a custom exception to be thrown is passed as a second argument to assert()
the only INI setting that has any effect is assert.active
, because if the assertion fails the custom exception is immediately thrown.
Moreover, the potentially set callback is not called.
Signature change of the assertion callback
In PHP 7 and previously, the assertion callback signature was as follows:
fn (string $filename, int $line_number, string $code, string $description = ?)
Where $code
represents the string evaluated assertion if provided or an empty string.
As of PHP 8.0, the signature of the callback is as follows:
fn (string $filename, int $line_number, null $code, string $description = ?)
Because the assert()
function now always provides null
instead of an empty string for the code argument.
Formal Proposal
- Formally deprecate the
assert_options()
function that was “soft deprecated” in PHP 7.0, by emitting anE_DEPRECATED
notice when it is called. - Deprecate the
assert.active
INI setting andASSERT_ACTIVE
constant, thezend_assertions
INI setting has superseded it for a while. - Deprecate the
assert.warning
INI setting andASSERT_WARNING
constant - Deprecate the
assert.bail
INI setting andASSERT_BAIL
constant - Deprecate the
assert.callback
INI setting andASSERT_CALLBACK
constant, thus deprecating this feature completely. - Deprecate the
assert.exception
INI setting andASSERT_EXCEPTION
constant
The behaviour of a deprecated INI setting is as follows:
A deprecation notice is only emitted if the value set in an INI file, or at runtime via ini_set()
differs from its default value.
Proposed PHP Version
Next minor version, i.e. PHP 8.3.
Proposed Voting Choices
As per the voting RFC a yes/no vote with a 2/3 majority is needed for this proposal to be accepted.
Voting started on 2023-06-28 and will end on 2023-07-12.
Implementation
Implemented in PHP 8.3:
- a link to the PHP manual entry for the feature