Starting with release 9.13.012, Scriptcase is now compatible with PHP 8.2, both in the development environment and in production.
When upgrading the environment to PHP 8.2, custom code (events, methods, and internal or external libraries) may start emitting warnings/deprecations or even fail, depending on the use of deprecated features or features with changed behavior.
Below are the most relevant PHP 8.2 changes.
1) Dynamic properties — Deprecated
In PHP 8.2, creating properties that do not exist in the class directly on an object (for example, obj->new = 1;) now triggers a deprecation notice.
This behavior is only allowed when the class itself explicitly allows dynamic properties or when the object is of type stdClass.
Before (no warning):
It was possible to create dynamic properties on objects without PHP emitting any warning.
-
class User {} $u = new User();
- $u->name = "Ana"; // dynamic property
PHP 8.2 (triggers deprecation):
This type of usage now triggers a deprecation notice. To avoid the warning, you can:
- Declare the property directly in the class;
Use the #[\AllowDynamicProperties] attribute (temporary workaround);
Use WeakMap when you do not control the class.
2) “Relative callables” — Deprecated
Some callable formats that worked with call_user_func(), but do not work correctly when executed as $callable(), have been marked as deprecated in PHP 8.2. This includes calls that depend on the class context, such as "self::method", "parent::method", "static::method" and ["self", "method"]
Avoid using:
- call_user_func("self::doStuff");
- call_user_func(["self", "doStuff"]);
Use instead:
The full class name:
- call_user_func("MyClass::doStuff");
- call_user_func(["MyClass", "doStuff"]);
Or a closure, when you need access to the current context:
- call_user_func(fn() => $this->doStuff());
3) Interpolation "${var}" and "${expr}" in strings — Deprecated
In PHP 8.2, using interpolation in the format "${var}" and "${expr}" in strings has been marked as deprecated, because this style is less clear and can be ambiguous.
Avoid:
- echo "Hello ${name}";
- echo "Total: ${arr['total']}";
Use:
- echo "Hello $name";
- echo "Hello {$name}";
- echo "Total: {${arr['total']}}"; // for expressions
4) utf8_encode() and utf8_decode() — Deprecated
The utf8_encode() and utf8_decode() functions have been marked as deprecated in PHP 8.2, because they assume a fixed encoding, which can lead to incorrect results in different scenarios.
Common replacements:
-
mb_convert_encoding($str, 'UTF-8', 'ISO-8859-1') // adjust the source encoding as needed
-
iconv('ISO-8859-1', 'UTF-8//TRANSLIT', $str) // when applicable
These functions assume ISO-8859-1 as the default encoding, which can cause confusion and incorrect conversions; that is why they were deprecated.
5) “Case-insensitive” functions and uppercase/lowercase conversion — Behavior change
In PHP 8.2, several functions that convert or compare text while ignoring case now use ASCII rules (the default “C” locale). This includes functions such as strtolower(), strtoupper(), ucwords() and str_ireplace().
With this change, these functions no longer follow language-specific rules, which can affect accented text or languages with special capitalization rules, such as Portuguese (pt-BR) and Turkish (tr-TR).
To properly handle localized text or accented characters, use the MBString extension, for example:
- mb_strtolower($texto, 'UTF-8');
6) glob() with open_basedir — Return value change
In PHP 8.2, the behavior of the glob() function changed when the open_basedir directive is enabled.
- If all paths are blocked by open_basedir, glob() now returns an empty array ([]) — previously, it returned false.
- If only some paths are blocked, a warning may be displayed.
Code that may be affected:
- $files = glob($pattern);
- if ($files === false) {
- // ...
- }
Recommended adjustment:
Update the check to also handle the [] return value, ensuring the code properly covers both cases.
Fix (handle false and []):
- $files = glob($pattern);
- if ($files === false || $files === []) {
- // No files found OR access blocked by open_basedir
- // handle it here (fallback, log, etc.)
- } else {
- foreach ($files as $file) {
- // process the files
- }
- }
Shorter alternative (when you do not need to distinguish false from []):
- $files = glob($pattern);
- if (empty($files)) {
- // empty ([]) or false
- } else {
- foreach ($files as $file) {
- // ...
- }
- }
7) Other behaviors that may cause “side effects” (less common)
In PHP 8.2, some smaller changes may cause different results in code that relies on the exact returned value or on the order of data.
str_split("") now returns []
This can affect validations that always expect at least one item in the array.
- var_dump(str_split(""));
- // PHP 8.2: array(0) { }
- // Before: array(1) { [0]=> string(0) "" }
var_export() and fully qualified class names
The var_export() function now exports class names using the fully qualified name (including \), especially when the class is inside a namespace.
This can cause differences in automated tests, snapshots, or string comparisons.
- namespace App\Model;
- class User {}
- echo var_export(new User(), true);
- // PHP 8.2: \App\Model\User::__set_state(array(
- // ...
- // ))
ksort() / krsort() with SORT_REGULAR and numeric strings
In some cases, the order of elements may change when the array keys are numeric strings.
For example, "2" and "10", because they follow the current comparison rules.
- $a = ["10" => "dez", "2" => "dois", "1" => "um"];
- ksort($a, SORT_REGULAR);
- var_dump(array_keys($a));
- krsort($a, SORT_REGULAR);
- var_dump(array_keys($a));