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
and ASSERT_ACTIVE
assert.warning
and ASSERT_WARNING
assert.bail
and ASSERT_BAIL
assert.callback
and ASSERT_CALLBACK
assert.exception
and ASSERT_EXCEPTION
which were introduced in PHP 7.0We will now explain what each of these settings does:
Enabled by default. If disabled, any call to the assert()
function will immediately return true
.
Otherwise, the assertion is executed.
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.
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.
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.
Enabled by default. If enabled, an AssertionError
or a custom exception is thrown if an assertion fails.
With the removal of the string evaluated assertion in PHP, some unintended behavioural changes were made.
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.
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.
assert_options()
function that was “soft deprecated” in PHP 7.0, by emitting an E_DEPRECATED
notice when it is called.assert.active
INI setting and ASSERT_ACTIVE
constant, the zend_assertions
INI setting has superseded it for a while.assert.warning
INI setting and ASSERT_WARNING
constantassert.bail
INI setting and ASSERT_BAIL
constantassert.callback
INI setting and ASSERT_CALLBACK
constant, thus deprecating this feature completely.assert.exception
INI setting and ASSERT_EXCEPTION
constantThe 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.
Next minor version, i.e. PHP 8.3.
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.
Implemented in PHP 8.3: