lunes, 10 de agosto de 2026

Testeos de nulidad en PHP

 ¿cómo se pregunta en php si un array asociativo que viene de un casteo de un json de un modelo eloquent tiene cierta propiedad?

En PHP, para preguntar si un array asociativo (que viene de un JSON casteado) tiene una cierta propiedad, usás isset() o array_key_exists(). La diferencia es sutil pero importante.


🔍 Los métodos y sus diferencias

Método¿Qué verifica?¿Considera null como existente?
isset($array['clave'])Que la clave exista y su valor no sea null❌ No (si es null, devuelve false)
array_key_exists('clave', $array)Que la clave exista, sin importar su valor✅ Sí (devuelve true incluso si es null)
property_exists($objeto, 'propiedad')Para objetos, no para arraysN/A

📝 Ejemplos

php
$documento = $odontograma->json; // Array asociativo

// ✅ Verificar si existe 'dentadura' (puede ser null)
if (array_key_exists('dentadura', $documento)) {
    // La clave existe, incluso si su valor es null
    $dentadura = $documento['dentadura'];
}

// ✅ Verificar si existe y no es null
if (isset($documento['dentadura'])) {
    // La clave existe Y su valor NO es null
    $dentadura = $documento['dentadura'];
}

// ✅ Verificar con null coalescing (PHP 7+)
$dentadura = $documento['dentadura'] ?? []; // Si no existe o es null, asigna []

// ✅ Verificar con null coalescing y operador de navegación (PHP 8+)
$casillero = $documento['dentadura'][0]['casillero'] ?? null;

🎯 Para tu caso específico

php
// app/Http/Controllers/PropuestaTratamientoController.php

public function generar(Paciente $paciente)
{
    $odontograma = $paciente->odontograma;
    $documento = $odontograma->json;

    // Opción 1: isset (si sabemos que debe tener valor)
    if (isset($documento['dentadura'])) {
        $dentadura = $documento['dentadura'];
    } else {
        $dentadura = [];
    }

    // Opción 2: array_key_exists (si puede ser null y queremos distinguir)
    if (array_key_exists('dentadura', $documento)) {
        $dentadura = $documento['dentadura'] ?? [];
    } else {
        $dentadura = [];
    }

    // Opción 3: Null coalescing (la más limpia)
    $dentadura = $documento['dentadura'] ?? [];
    $marcas = $documento['marcas_dentales'] ?? [];
    $soluciones = $documento['soluciones'] ?? [];
    $problemas = $documento['problemas'] ?? [];
    $enlaces = $documento['enlaces'] ?? [];

    // ... resto
}

⚠️ Cuidado con isset() y valores null

php
$data = ['nombre' => null];

isset($data['nombre']);        // false (porque es null)
array_key_exists('nombre', $data); // true (la clave existe)

// Por eso, si el JSON puede tener claves con valor null,
// y necesitás saber si la clave existe, usá array_key_exists.

📌 Recomendación para tu código

Usá null coalescing (??) para la mayoría de los casos, porque es limpio y seguro:

php
$dentadura = $documento['dentadura'] ?? [];
$marcas = $documento['marcas_dentales'] ?? [];
$soluciones = $documento['soluciones'] ?? [];

Si necesitás saber si la clave existe pero puede ser null, usá array_key_exists().


¿Tenías algún caso específico en mente donde necesites diferenciar entre "clave no existe" y "clave existe con valor null"?

¿Hay diferencia entre isset($documento['dentadura']) y $documento['dentadura']!=null?

Sí, hay diferencias importantes. Aunque en muchos casos parecen equivalentes, no lo son.


🔍 Comparación Detallada

Expresión¿Qué verifica?¿Qué pasa si...
isset($documento['dentadura'])Que la clave exista y su valor no sea null✅ Devuelve true si existe y no es null
❌ Devuelve false si no existe o es null
$documento['dentadura'] != nullQue el valor no sea null (con coerción de tipos)⚠️ ERROR si la clave no existe (PHP lanza Undefined array key)

📝 Ejemplos Prácticos

php
$documento = ['dentadura' => null];

// Caso 1: La clave existe pero es null
isset($documento['dentadura']);        // false (porque es null)
$documento['dentadura'] != null;       // false (porque es null)

// Caso 2: La clave no existe
isset($documento['no_existe']);        // false (no existe)
$documento['no_existe'] != null;       // ❌ ERROR: Undefined array key "no_existe"

// Caso 3: La clave existe con valor
$documento = ['dentadura' => ['pieza' => 1]];
isset($documento['dentadura']);        // true
$documento['dentadura'] != null;       // true

// Caso 4: La clave existe con valor 0 (cero)
$documento = ['cantidad' => 0];
isset($documento['cantidad']);         // true (0 no es null)
$documento['cantidad'] != null;        // true (0 no es null)

⚠️ Problemas con != null

El operador != hace coerción de tipos, lo que puede dar resultados inesperados:

php
$documento = ['valor' => ''];

$documento['valor'] != null;  // false (string vacío se considera null en comparación suelta)
$documento['valor'] !== null; // true (comparación estricta, '' !== null)

📊 Comparación de Métodos

Método¿Evita error si no existe?¿Distingue entre no existe y null?Considera 0 como existente
isset($arr['key'])✅ Sí❌ No (null = no existe)✅ Sí
array_key_exists('key', $arr)✅ Sí✅ Sí✅ Sí
$arr['key'] != nullERROR❌ No (depende de la coerción)✅ Sí
$arr['key'] ?? null✅ Sí❌ No (null = no existe)✅ Sí

🎯 Recomendación para tu Código

Si solo querés saber si existe y tiene valor:

php
if (isset($documento['dentadura'])) {
    // Existe y no es null
    $dentadura = $documento['dentadura'];
}

Si querés saber si existe, aunque sea null:

php
if (array_key_exists('dentadura', $documento)) {
    // Existe, puede ser null o tener valor
    $dentadura = $documento['dentadura'];
}

Si querés asignar un valor por defecto (lo más común):

php
$dentadura = $documento['dentadura'] ?? [];

Si necesitás diferenciar entre no existe y null (menos común):

php
if (array_key_exists('dentadura', $documento)) {
    if ($documento['dentadura'] === null) {
        // Existe pero es null
    } else {
        // Existe y tiene valor
    }
}

Conclusión

NUNCA uses $documento['dentadura'] != null sin antes verificar que la clave exista con isset() o array_key_exists(). Es una receta segura para errores Undefined array key.

Usá ?? (null coalescing) para asignaciones seguras y isset() para condiciones simples.

¿Y la función empty tiene algo que ver con todo esto?

Sí, empty() está relacionada pero tiene un comportamiento muy particular que la hace diferente a isset() y a la comparación con null.


🔍 empty() en profundidad

empty() verifica si una variable no existe o su valor se considera "vacío" según una lista predefinida de valores.

php
empty($variable);

📋 Valores que empty() considera como "vacíos"

Valor¿empty() devuelve true?
null✅ Sí
'' (string vacío)✅ Sí
0 (int 0)✅ Sí
0.0 (float 0)✅ Sí
'0' (string "0")✅ Sí
[] (array vacío)✅ Sí
false✅ Sí
Variable no definida✅ Sí
'hola' (string con contenido)❌ No
[1,2] (array con elementos)❌ No
true❌ No

📊 Comparación: empty() vs isset() vs ?? vs != null

Situaciónisset()empty()??!= null
Clave no existefalse (sin error)true (sin error)valor_defectoERROR
nullfalsetruevalor_defectofalse
'' (string vacío)truetrue''false
0 (int)truetrue0false
'0' (string "0")truetrue'0'false
falsetruetruefalsefalse
[] (array vacío)truetrue[]false
'hola'truefalse'hola'true

📝 Ejemplos Prácticos

php
$documento = [
    'dentadura' => null,
    'nombre' => '',
    'cantidad' => 0,
    'marcas' => [],
    'activo' => false,
];

// 👇 Comportamientos diferentes
isset($documento['dentadura']);   // false (es null)
empty($documento['dentadura']);   // true  (es null)
$documento['dentadura'] ?? 'def'; // 'def'

isset($documento['nombre']);      // true  (existe)
empty($documento['nombre']);      // true  (es string vacío)
$documento['nombre'] ?? 'def';    // '' (no aplica)

isset($documento['cantidad']);    // true  (existe)
empty($documento['cantidad']);    // true  (es 0)
$documento['cantidad'] ?? 'def';  // 0 (no aplica)

isset($documento['marcas']);      // true  (existe)
empty($documento['marcas']);      // true  (es array vacío)
$documento['marcas'] ?? 'def';    // [] (no aplica)

🎯 ¿Cuándo usar cada uno?

Usá isset() cuando...

  • Querés saber si una clave existe y no es null

  • Necesitás distinguir entre "no existe" y "existe pero es null"

php
if (isset($documento['dentadura'])) {
    // Existe y tiene un valor que no es null
}

Usá empty() cuando...

  • Querés saber si una variable está disponible y tiene contenido significativo

  • Considerás '', 0, '0', [], false, null como "sin contenido"

php
if (!empty($documento['dentadura'])) {
    // Existe y tiene contenido "significativo"
    // (no es null, no es '', no es 0, no es [], no es false)
}

Usá ?? (null coalescing) cuando...

  • Querés asignar un valor por defecto solo si la clave no existe o es null

php
$dentadura = $documento['dentadura'] ?? [];

Usá ??= (null coalescing assignment) en PHP 7.4+ cuando...

  • Querés asignar un valor por defecto solo si la variable es null o no existe

php
$dentadura ??= []; // Si no existe o es null, asigna []

Usá el operador ?: (ternario) cuando...

  • Querés asignar un valor por defecto si la variable es "vacía" (según empty())

php
$dentadura = $documento['dentadura'] ?: [];
// Si es null, '', 0, '0', [], false → asigna []

⚠️ Cuidado con empty() en Laravel / Eloquent

En modelos Eloquent, empty() sobre una propiedad que no existe en la BD no lanza error porque Eloquent usa magic methods (__get). Pero el comportamiento puede ser confuso:

php
$odontograma = Odontograma::first();

// ❌ Esto NO funciona (acceder a propiedad que no existe)
empty($odontograma->propiedad_inexistente); // true

// ✅ Esto SÍ funciona (acceder a clave del JSON)
$json = $odontograma->json;
empty($json['dentadura']); // depende del valor

📌 Resumen para tu código

SituaciónExpresión recomendada
Asignar valor por defecto$valor = $arr['clave'] ?? 'default';
Verificar si existe y tiene valorif (isset($arr['clave']))
Verificar si tiene contenido significativoif (!empty($arr['clave']))
Verificar si existe (incluso si es null)if (array_key_exists('clave', $arr))
Asignar si está vacío (PHP 7.4+)$arr['clave'] ??= 'default';

¿Querés que te ayude a decidir cuál usar en un caso específico de tu código?

No hay comentarios: