Starting with release 9.13.012, Scriptcase is compatible with PHP 8.2, both in the development environment and in production.
When migrating directly from PHP 7.x to PHP 8.2, custom code (events, methods, and internal or external libraries) may start generating warnings, deprecations, or even fail, due to behavior changes and the discontinuation of features introduced in newer PHP versions.
This tutorial brings together the main points to watch for when migrating to PHP 8.2, with explanations and practical examples to help you adapt your code and reduce the impact during the update.
1) Nested ternary operators without explicit parentheses — Not allowed
Conditional expressions using nested ternary operators without explicit parentheses are not allowed in PHP 8.2.
This type of syntax can lead to ambiguities and is no longer accepted by the PHP interpreter.
❌ Not allowed example:
- $result = $aa != "" ? $xxx : isset($bb) && $bb != "" ? $zzz : "";
✅ Recommended approach:
Rewrite the logic explicitly using conditional structures:
- if ($aa != "") {
- $result = $xxx;
- } elseif (isset($bb) && $bb != "") {
- $result = $zzz;
- } else {
- $result = "";
- }
2) Accessing array and string values using curly braces — Deprecated
Accessing values from arrays and strings using the curly braces syntax {} is not allowed in PHP 8.2.
This format is deprecated and may generate warnings or runtime errors.
Always use square brackets [] to access indexes.
❌ Not allowed example:
- $array = [1, 2];
- echo $array{1};
- $string = "foo";
- echo $string{0};
This type of access generates messages such as:
Deprecated: Array and string offset access syntax with curly braces is deprecated
✅ Correct approach:
- $array = [1, 2];
- echo $array[1]; // outputs 2
- $string = "foo";
- echo $string[0]; // outputs "f"
3) Required parameters after optional parameters — Deprecated
Declaring functions or methods with required parameters after optional parameters is not allowed in PHP 8.2.
This type of signature is considered incorrect and may generate warnings or deprecations at runtime.
❌ Not allowed example:
- function foo($param_optional = null, $param_required) {
- // ...
- }
This type of declaration may generate messages such as:
Deprecated: Required parameter $param_required follows optional parameter $param_optional
✅ Correct approach:
Always declare required parameters first, followed by optional parameters:
- function foo($param_required, $param_optional = null) {
- // ...
- }
4) Arithmetic operations with non-numeric strings — Not allowed
Arithmetic operations involving non-numeric strings are not allowed in PHP 8.2.
This type of operation may generate warnings or errors, because values that do not represent numbers are no longer implicitly treated as zero.
❌ Not allowed example:
This type of operation may result in an error because $b does not contain a valid numeric value.
✅ Correct approach:
Before performing the operation, make sure the value is numeric.
Example 1 — direct validation:
- $a = is_numeric($b) ? $b + 2 : 2;
Example 2 — value normalization:
- if (!is_numeric($b)) {
- $b = 0;
- }
- $a = $b + 2;
5) Non-existent variables and indexes — Watch out for warnings
Using undefined variables or non-existent array indexes may generate warnings in PHP 8.2.
This happens when the code tries to access values that have not been defined yet.
If warnings are enabled, these situations may result in frequent messages during runtime.
❌ Not recommended example:
Or:
When $b or $array['key'] do not exist, a warning may be displayed.
✅ Correct approach:
Before using a variable or an array index, check whether it exists.
- $a = isset($b) ? $b + 2 : 2;
Or, for arrays:
- $a = isset($array['key']) ? $array['key'] + 2 : 2;
6) `each()` function — Removed
The each() function returns the current key/value pair of an array and advances its internal pointer.
This function is not available in PHP 8.2.
If it is used in your applications, the code must be updated before deploying to an environment with PHP 8.2 or higher.
Common replacement options:
- foreach()
- key()
- current()
- next()
❌ Not supported example:
- $result = "";
- $tab = array(
- 0 => array('tp' => 1, 'vl' => 'aaa'),
- 1 => array('tp' => 2, 'vl' => 'bbb'),
- 2 => array('tp' => 3, 'vl' => 'ccc')
- );
- while (list($key, $val) = each($tab)) {
- $result .= $tab[$key]["vl"];
- }
✅ Recommended approach (using foreach()):
- $result = "";
- $tab = array(
- 0 => array('tp' => 1, 'vl' => 'aaa'),
- 1 => array('tp' => 2, 'vl' => 'bbb'),
- 2 => array('tp' => 3, 'vl' => 'ccc')
- );
- foreach ($tab as $key => $val) {
- $result .= $tab[$key]["vl"];
- }
7) `array_key_exists()` function — Using it on objects is deprecated
The array_key_exists() function checks whether a key or index exists in an array.
In PHP 8.2, using this function to check object properties is deprecated.
For this scenario, use isset() or property_exists().
❌ Not recommended example:
- if (array_key_exists('index', $array1)) {
- // code
- }
✅ Recommended approach:
- if (isset($array1['index'])) {
- // code
- }
The money_format() function formats a number as a currency string.
This function is not available in PHP 8.2.
To format currency values, use the Intl extension through the NumberFormatter class.
❌ Not supported example:
- echo money_format("%.2n", 1234.56);
✅ Recommended approach (using NumberFormatter):
- $currencyObject = new NumberFormatter("pt-BR", NumberFormatter::CURRENCY);
- echo $currencyObject->format(1234.56);
9) `mb_strrpos()` function — Encoding parameter is deprecated
The mb_strrpos() function finds the position of the last occurrence of a value in a string.
In PHP 8.2, passing the encoding as the third parameter is deprecated.
Instead, pass an offset as the third parameter and the encoding as the fourth.
❌ Not recommended example:
- $string = 'O rato roeu a roupa';
- echo mb_strrpos($string, 'roeu', 'UTF-8');
✅ Correct approach:
- $string = 'O rato roeu a roupa';
- echo mb_strrpos($string, 'roeu', 0, 'UTF-8');
10) 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;) triggers a deprecation notice.
This behavior is only allowed when the class explicitly permits 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 warnings.
- 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 it, you can:
- Declare the property directly in the class;
- Use the #[\AllowDynamicProperties] attribute (temporary workaround);
- Use WeakMap when you do not have control over the class.
11) 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 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 fully qualified 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());
12) "${var}" and "${expr}" interpolation in strings — Deprecated
In PHP 8.2, using string interpolation in the "${var}" and "${expr}" formats has been marked as deprecated, as this style is less clear and may cause ambiguity.
Avoid:
- echo "Hello ${name}";
- echo "Total: ${arr['total']}";
Use:
- echo "Hello $name";
- echo "Hello {$name}";
- echo "Total: {${arr['total']}}"; // for expressions
13) utf8_encode() and utf8_decode() — Deprecated
The utf8_encode() and utf8_decode() functions have been marked as deprecated in PHP 8.2, as they assume a fixed encoding, which may 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 may cause confusion and incorrect conversions; therefore, they were deprecated.
14) Case-insensitive functions and uppercase/lowercase conversion — Behavior change
In PHP 8.2, several functions that convert or compare text in a case-insensitive way now follow ASCII rules (default “C” locale). This includes functions such as strtolower(), strtoupper(), ucwords(), and str_ireplace().
With this change, these functions no longer consider language-specific rules, which may affect accented characters or languages with special capitalization rules, such as Portuguese (pt-BR) and Turkish (tr-TR).
To correctly handle localized text or accented characters, use the MBString extension, for example:
- mb_strtolower($text, 'UTF-8');
15) 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 consider the [] return value, ensuring the code properly handles both scenarios.
Fix (handle false and []):
- $files = glob($pattern);
- if ($files === false || $files === []) {
- // No files found OR access blocked by open_basedir
- // handle it here (fallback, logging, etc.)
- } else {
- foreach ($files as $file) {
- // process files
- }
- }
Shorter alternative (when you do not need to differentiate false from []):
- $files = glob($pattern);
- if (empty($files)) {
- // empty ([]) or false
- } else {
- foreach ($files as $file) {
- // ...
- }
- }
16) Other behaviors that may cause “side effects” (less common)
In PHP 8.2, some smaller changes may cause differences in results for code that depends exactly on return values or data ordering.
str_split("") now returns []
This may 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 may 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));