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.

1. *class User {} $u = new User();*
2. *$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:

1. 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:**

1. *call\_user\_func("self::doStuff");*
2. *call\_user\_func(["self", "doStuff"]);*

**Use instead:**

The full class name:

1. *call\_user\_func("MyClass::doStuff");*
2. *call\_user\_func(["MyClass", "doStuff"]);*

Or a closure, when you need access to the current context:

1. *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:**

1. *echo "Hello ${name}";*
2. *echo "Total: ${arr['total']}";*

**Use:**

1. *echo "Hello $name";*
2. *echo "Hello {$name}";*
3. *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:**

1. *mb\_convert\_encoding($str, 'UTF-8', 'ISO-8859-1') // adjust the source encoding as needed*
2. *iconv('ISO-8859-1', 'UTF-8//TRANSLIT', $str) // when applicable*

![Quote](https://static.zohocdn.com/zoho-desk-editor/static/images/quote.png/)

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:

1. *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.

1. If all paths are blocked by ***open\_basedir***, ***glob()*** now returns an empty array (**[]**) — **previously, it returned false.**
2. If only some paths are blocked, a **warning** may be displayed.

**Code that may be affected:**

1. *$files = glob($pattern);*
2. *if ($files === false) {*
3. *// ...*
4. *}*

**Recommended adjustment:**

Update the check to also handle the **[]** return value, ensuring the code properly covers both cases.

**Fix (handle** `false` **and** `[]`**):**

1. *$files = glob($pattern);*
2. *if ($files === false || $files === []) {*
3. *// No files found OR access blocked by open\_basedir*
4. *// handle it here (fallback, log, etc.)*
5. *} else {*
6. *foreach ($files as $file) {*
7. *// process the files*
8. *}*
9. *}*

**Shorter alternative (when you do not need to distinguish** `false` **from** `[]`**):**

1. *$files = glob($pattern);*
2. *if (empty($files)) {*
3. *// empty ([]) or false*
4. *} else {*
5. *foreach ($files as $file) {*
6. *// ...*
7. *}*
8. *}*

## 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*.

1. *var\_dump(str\_split(""));*
2. *// PHP 8.2: array(0) { }*
3. *// 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.

1. *namespace App\Model;*
3. *class User {}*
5. *echo var\_export(new User(), true);*
6. *// PHP 8.2: \App\Model\User::\_\_set\_state(array(*
7. *// ...*
8. *// ))*

***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.

1. *$a = ["10" => "dez", "2" => "dois", "1" => "um"];*
3. *ksort($a, SORT\_REGULAR);*
4. *var\_dump(array\_keys($a));*
6. *krsort($a, SORT\_REGULAR);*
7. *var\_dump(array\_keys($a));*