A partir de la release 9.13.012, Scriptcase pasa a ser compatible con PHP 8.2, tanto en el entorno de desarrollo como en producción.

Al migrar directamente de **PHP 7.x a PHP 8.2**, los códigos personalizados (eventos, métodos y bibliotecas internas o externas) pueden empezar a emitir *warnings*, *deprecations* o incluso presentar fallas, debido a cambios de comportamiento y a la eliminación de recursos introducidos en las versiones más recientes de PHP.

Este tutorial reúne los **principales puntos de atención de la migración a PHP 8.2**, con explicaciones y ejemplos prácticos para facilitar la adaptación del código y reducir impactos durante la actualización.

## 1) Operadores ternarios anidados sin paréntesis explícitos — No permitido

Las expresiones condicionales que usan operadores ternarios anidados sin paréntesis explícitos no están permitidas en PHP 8.2.

Este tipo de escritura puede generar ambigüedades y ya no es aceptado por el intérprete.

**❌ Ejemplo no permitido:**

1. $result = $aa != "" ? $xxx : isset($bb) && $bb != "" ? $zzz : "";

**✅ Forma recomendada:**

Reescribe la lógica de forma explícita, usando estructuras condicionales:

1. if ($aa != "") {
2. $result = $xxx;
3. } elseif (isset($bb) && $bb != "") {
4. $result = $zzz;
5. } else {
6. $result = "";
7. }

## 2) Acceso a valores de array y string usando llaves — Deprecated

El acceso a valores de ***arrays*** y *strings* usando la sintaxis con llaves **{}** no está permitido en PHP 8.2.

Este formato está depreciado y puede generar *warnings* o errores durante la ejecución.

Utiliza siempre la sintaxis con corchetes **[]** para acceder a índices.

**❌ Ejemplo no permitido:**

1. $array = [1, 2];
2. echo $array{1};
3. $string = "foo";
4. echo $string{0};

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

Este tipo de acceso genera mensajes como:

Deprecated: Array and string offset access syntax with curly braces is deprecated

**✅ Forma correcta:**

1. $array = [1, 2];
2. echo $array[1]; // muestra 2
3. $string = "foo";
4. echo $string[0]; // muestra "f"

## 3) Parámetros obligatorios después de parámetros opcionales — Deprecated

La declaración de funciones o métodos con **parámetros obligatorios después de parámetros opcionales** no está permitida en PHP 8.2.

Este tipo de firma se considera incorrecta y puede generar *warnings* o *deprecations* durante la ejecución.

**❌ Ejemplo no permitido:**

1. function foo($param\_optional = null, $param\_required) {
2. // ...
3. }

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

Este tipo de declaración puede generar mensajes como:

Deprecated: Required parameter $param\_required follows optional parameter $param\_optional

**✅ Forma correcta:**

Declara siempre primero los parámetros obligatorios, seguidos por los opcionales:

1. function foo($param\_required, $param\_optional = null) {
2. // ...
3. }

## 4) Operaciones aritméticas con strings no numéricos — No permitido

**Las operaciones aritméticas que involucran strings** **no numéricos** **no están permitidas en PHP 8.2**.

Este tipo de operación puede generar *warnings* o *errores*, ya que los valores que no representan números ya no se tratan implícitamente como cero.

**❌ Ejemplo no permitido:**

1. $b = "";
2. $a = $b + 2;

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

Este tipo de operación puede provocar un error, ya que **$b** no contiene un valor numérico válido.

**✅ Forma correcta:**

Antes de realizar la operación, es necesario garantizar que el valor sea numérico.

**Ejemplo 1 — validación directa:**

1. $a = is\_numeric($b) ? $b + 2 : 2;

**Ejemplo 2 — normalización del valor:**

1. if (!is\_numeric($b)) {
2. $b = 0;
3. }
4. $a = $b + 2;

## 5) Variables e índices inexistentes — Atención a warnings

El uso de **variables no definidas** o **índices de array inexistentes** puede generar *warnings* en PHP 8.2.

Este comportamiento ocurre cuando el código intenta acceder a valores que aún no han sido definidos.

Si la visualización de *warnings* está habilitada, este tipo de situación puede generar mensajes frecuentes durante la ejecución del código.

**❌ Ejemplo no permitido:**

1. $a = $b + 2;

O:

1. $a = $array['key'] + 2;

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

Cuando **$b** o **$array['key']** no existen, puede mostrarse un warning.

**✅ Forma correcta:**

Antes de utilizar una variable o un índice de array, verifique si existe.

1. $a = isset($b) ? $b + 2 : 2;

O, en el caso de arrays:

1. $a = isset($array['key']) ? $array['key'] + 2 : 2;

## 6) Función each() — Eliminada

La función ***each()*** devuelve el par **clave/valor** actual de un *array* y avanza su cursor interno.

Esta función **no está disponible en PHP 8.2**.

Si se utiliza en sus aplicaciones, el código **debe ser modificado** antes de publicarse en un entorno con PHP 8.2 o superior.

**Opciones comunes de sustitución:**

1. ***foreach()***
2. ***key()***
3. ***current()***
4. ***next()***

**❌ Ejemplo no soportado:**

1. $result = "";
3. $tab = array(
4. 0 => array('tp' => 1, 'vl' => 'aaa'),
5. 1 => array('tp' => 2, 'vl' => 'bbb'),
6. 2 => array('tp' => 3, 'vl' => 'ccc')
7. );
9. while (list($key, $val) = each($tab)) {
10. $result .= $tab[$key]["vl"];
11. }

**✅ Forma recomendada (usando foreach()):**

1. $result = "";
3. $tab = array(
4. 0 => array('tp' => 1, 'vl' => 'aaa'),
5. 1 => array('tp' => 2, 'vl' => 'bbb'),
6. 2 => array('tp' => 3, 'vl' => 'ccc')
7. );
9. foreach ($tab as $key => $val) {
10. $result .= $tab[$key]["vl"];
11. }

## 7) Función array\_key\_exists() — Uso en objetos deprecated

La función **array\_key\_exists()** verifica si una **clave o índice existe en un array**.

En PHP 8.2, el uso de esta función para verificar **propiedades de objetos** está marcado como **deprecated**.

Para este escenario, utilice **isset()** o **property\_exists()**.

**❌ Ejemplo no recomendado:**

1. if (array\_key\_exists('index', $array1)) {
2. // código
3. }

**✅ Forma recomendada:**

1. if (isset($array1['index'])) {
2. // código
3. }

## 8) Función money\_format() — Eliminada

La función ***money\_format()*** formatea un número como una cadena de moneda.

Esta función **no está disponible en PHP 8.2**.

Para realizar el formato monetario, utilice la extensión **Intl** mediante la clase **NumberFormatter**.

**❌ Ejemplo no soportado:**

1. echo money\_format("%.2n", 1234.56);

**✅ Forma recomendada (usando NumberFormatter):**

1. $currencyObject = new NumberFormatter("es-ES", NumberFormatter::CURRENCY);
2. echo $currencyObject->format(1234.56);

## 9) Función mb\_strrpos() — Parámetro de encoding deprecated

La función **mb\_strrpos()** localiza la **última ocurrencia** de un valor dentro de una *cadena*.

En PHP 8.2, pasar la **codificación como tercer parámetro** está marcado como **deprecated**.

En su lugar, pase un **offset** como tercer parámetro y la **codificación como cuarto**.

**❌ Ejemplo no recomendado:**

1. $string = 'El ratón roió la ropa';
2. echo mb\_strrpos($string, 'roió', 'UTF-8');

**✅ Forma correcta:**

1. $string = 'El ratón roió la ropa';
2. echo mb\_strrpos($string, 'roió', 0, 'UTF-8');

## 10) Propiedades dinámicas (dynamic properties) — Deprecated

En PHP 8.2, crear propiedades que no existen en la clase directamente en un objeto (por ejemplo, ***obj->nueva = 1;***) pasa a generar una advertencia de **deprecation**.

Este comportamiento solo está permitido cuando la propia clase autoriza la creación dinámica de propiedades o cuando el objeto es del tipo ***stdClass***.

**Antes (sin aviso):**

Era posible crear propiedades dinámicamente en objetos sin que PHP emitiera ningún aviso.

1. *class User {} $u = new User();*
2. *$u->name = "Ana"; // propiedad dinámica*

**PHP 8.2 (genera deprecation):**

Este tipo de uso pasa a generar una advertencia de deprecation. Para evitar el aviso, puede:

1. Declarar la propiedad directamente en la clase;
2. Usar el atributo #[\AllowDynamicProperties] (solución paliativa);
3. Utilizar WeakMap cuando no se tiene control sobre la clase.

## 11) “Relative callables” — Deprecated

Algunos formatos de *callable* que funcionaban con `call_user_func()`, pero no funcionan correctamente cuando se ejecutan como `$callable()`, pasaron a estar marcados como **deprecated** en PHP 8.2.

Esto incluye llamadas que dependen del contexto de la clase, como `"self::method"`, `"parent::method"`, `"static::method"` y `["self", "method"]`.

**❌ Evite usar:**

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

**✅ Use en su lugar:**

El nombre completo de la clase:

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

O una *closure*, cuando sea necesario acceder al contexto actual:

1. *call\_user\_func(fn() => $this->doStuff());*

## 12) Interpolación "${var}" y "${expr}" en strings — Deprecated

En PHP 8.2, el uso de interpolación en el formato `"${var}"` y `"${expr}"` dentro de cadenas pasó a estar marcado como **deprecated**, ya que este estilo es menos claro y puede generar ambigüedades.

**❌ Evite:**

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

**✅ Use:**

1. *echo "Hola $name";*
2. *echo "Hola {$name}";*
3. *echo "Total: {${arr['total']}}"; // para expresiones*

## 13) utf8\_encode() y utf8\_decode() — Deprecated

Las funciones ***utf8\_encode()*** y ***utf8\_decode()*** fueron marcadas como **deprecated** en PHP 8.2, ya que asumen una codificación fija, lo que puede generar resultados incorrectos en distintos escenarios.

**Sustituciones comunes:**

1. *mb\_convert\_encoding($str, 'UTF-8', 'ISO-8859-1') // ajuste la codificación de origen según el caso*
2. *iconv('ISO-8859-1', 'UTF-8//TRANSLIT', $str) // cuando sea aplicable*

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

Estas funciones asumen la codificación **ISO-8859-1** por defecto, lo que puede causar confusión y conversiones incorrectas; por ello fueron descontinuadas.

## 14) Funciones “case-insensitive” y conversión de mayúsculas/minúsculas — Cambio de comportamiento

En PHP 8.2, varias funciones que convierten o comparan texto ignorando mayúsculas y minúsculas pasaron a utilizar reglas **ASCII** (locale por defecto “C”).

Esto incluye funciones como ***strtolower()***, ***strtoupper()***, ***ucwords()*** y ***str\_ireplace()***.

Con este cambio, estas funciones ya no consideran reglas específicas de idioma, lo que puede afectar textos con acentos o idiomas con reglas propias de capitalización, como portugués (**pt-BR**) y turco (**tr-TR**).

Para trabajar correctamente con textos localizados o caracteres acentuados, utilice la extensión **MBString**, por ejemplo:

1. *mb\_strtolower($texto, 'UTF-8');*

## 15) glob() con open\_basedir — Cambio en el retorno

En PHP 8.2, el comportamiento de la función ***glob()*** cambió cuando la directiva ***open\_basedir*** está activa.

1. Si todas las rutas están bloqueadas por ***open\_basedir***, ***glob()*** devuelve un array vacío (**[]**) — antes devolvía **false**.
2. Si solo algunas rutas están bloqueadas, puede mostrarse un **warning**.

**Código que puede verse afectado:**

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

**Ajuste recomendado:**

Actualice la verificación para considerar también el retorno **[]**, asegurando que el código maneje correctamente ambos escenarios.

**Corrección (manejar** `false` **y** `[]`**):**

1. *$files = glob($pattern);*
2. *if ($files === false || $files === []) {*
3. *// Ningún archivo encontrado O acceso bloqueado por open\_basedir*
4. *// maneje aquí (fallback, log, etc.)*
5. *} else {*
6. *foreach ($files as $file) {*
7. *// procesa los archivos*
8. *}*
9. *}*

**Alternativa más corta (cuando no es necesario diferenciar** `false` **de** `[]`**):**

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

## 16) Otros comportamientos que pueden generar “efectos secundarios” (menos comunes)

En PHP 8.2, algunos cambios menores pueden causar diferencias en los resultados de códigos que dependen exactamente del valor retornado o del orden de los datos.

### **str\_split("") ahora devuelve []**

Esto puede afectar validaciones que esperan siempre al menos un elemento en el *array*.

1. *var\_dump(str\_split(""));*
2. *// PHP 8.2: array(0) { }*
3. *// Antes: array(1) { [0] => string(0) "" }*

### `var_export()` y nombres de clases totalmente calificados

La función `var_export()` pasó a exportar los nombres de las clases utilizando el nombre **totalmente calificado** (incluyendo `\`), especialmente cuando la clase se encuentra dentro de un *namespace*.

Esto puede generar diferencias en pruebas automatizadas, snapshots o comparaciones de *string*.

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

### ***ksort()*** / ***krsort()*** con ***SORT\_REGULAR*** y strings numéricas

En algunos casos, el orden de los elementos puede cambiar cuando las claves del *array* son *strings* numéricas, por ejemplo `"2"` y `"10"`.

1. *$a = ["10" => "diez", "2" => "dos", "1" => "uno"];*
2. *ksort($a, SORT\_REGULAR);*
3. *var\_dump(array\_keys($a));*
4. *krsort($a, SORT\_REGULAR);*
5. *var\_dump(array\_keys($a));*