---
title: "== vs === en PHP: igualdad suelta vs estricta"
excerpt: "La diferencia entre == y === en PHP explicada con ejemplos: conversión de tipos, el cambio de PHP 8, los gotchas de switch e in_array, y cómo comparar arrays y objetos."
date: "2026-06-16T00:00:00.000Z"
lastModified: "2026-06-16T00:00:00.000Z"
category: "PHP"
author:
  name: "angel cruz"
  picture: "https://angelcruzdevcdn.nyc3.cdn.digitaloceanspaces.com/images/me/angel-cruz.png"
ogImage:
  url: "/images/open-graph/php-opengraph-image.png"
seo_title: "== vs === en PHP: diferencia entre igual e idéntico"
seo_description: "Diferencia entre == y === en PHP con ejemplos: == compara valor (con conversión de tipos), === compara valor y tipo. El cambio de PHP 8 y los gotchas de switch e in_array."
tech_article:
  article_section: "PHP Fundamentals"
  keywords: "== vs === php, diferencia == y === php, igualdad estricta php, comparacion php, operador identico php"
  is_part_of:
    url: "https://www.angelcruz.dev/post/operadores-php"
---

En PHP, `==` compara **solo el valor** (aplicando conversión de tipos), mientras que `===` compara **valor y tipo**. Por eso `5 == "5"` es `true`, pero `5 === "5"` es `false`. La regla práctica: usa `===` por defecto. Evita los bugs sutiles que provoca la conversión automática de tipos.

Este artículo forma parte de la [guía de operadores en PHP](/post/operadores-php). Aquí me enfoco en la comparación que más confunde.

## `==` : igualdad con conversión de tipos

El operador `==` (igual) devuelve `true` cuando los dos operandos tienen el **mismo valor**, incluso si son de tipos distintos. Antes de comparar, PHP convierte uno de los operandos para que ambos sean del mismo tipo. A esto se le llama *type juggling*:

```php
var_dump(5 == "5");      // true  — la string "5" se trata como el número 5
var_dump(true == 1);     // true  — true equivale a 1
var_dump(null == false); // true  — ambos son "vacíos"
var_dump(0 == false);    // true
```

Es cómodo, pero peligroso: ese ajuste automático esconde comparaciones que no son las que esperas.

## `===` : identidad (valor y tipo)

El operador `===` (idéntico) devuelve `true` solo si los operandos tienen el **mismo valor y el mismo tipo**. No hay conversión de por medio:

```php
var_dump(5 === "5");      // false — int vs string
var_dump(true === 1);     // false — bool vs int
var_dump(null === false); // false — null vs bool
var_dump(5 === 5);        // true  — mismo valor, mismo tipo
```

Es la comparación segura y predecible. Lo que ves es lo que se compara.

## Tabla de comparación

| Expresión | `==` | `===` |
|---|---|---|
| `5` y `"5"` | `true` | `false` |
| `0` y `false` | `true` | `false` |
| `null` y `false` | `true` | `false` |
| `"" ` y `null` | `true` | `false` |
| `"1"` y `"01"` | `true` | `false` |
| `"10"` y `"1e1"` | `true` | `false` |
| `0` y `"foo"` (PHP 8) | `false` | `false` |
| `5` y `5` | `true` | `true` |

Fíjate en `"1" == "01"` y `"10" == "1e1"`: cuando **ambos** operandos son strings numéricas, PHP las compara como números. Por eso `"01"` y `"1e1"` (notación científica de 10) entran en juego. Con `===` nunca pasa: distinto string, distinto resultado.

## El cambio de PHP 8 que rompe código viejo

Hasta PHP 7, comparar un número con una string **no numérica** convertía la string a `0`. Eso hacía que `0 == "foo"` fuera `true`, una de las fuentes de bugs más clásicas del lenguaje. PHP 8 lo cambió: ahora convierte el número a string:

```php
// PHP 7: true   |   PHP 8: false
var_dump(0 == "foo");

// PHP 7: true   |   PHP 8: false
var_dump(0 == "");
```

Si migras un proyecto de PHP 7 a 8, este es uno de los cambios de comportamiento que más vale revisar. Y es, otra vez, un argumento a favor de usar `===`.

## `!=` vs `!==` (las versiones negadas)

La misma lógica aplica a la desigualdad:

- `!=` (o su alias `<>`) es la negación de `==`: `true` si los valores difieren tras la conversión de tipos.
- `!==` es la negación de `===`: `true` si difieren en valor **o** en tipo.

```php
var_dump(5 != "5");   // false — para != son iguales (mismo valor)
var_dump(5 !== "5");  // true  — para !== difieren (distinto tipo)
```

## Dónde PHP usa `==` sin que lo veas

El gran problema de `==` no es cuando lo escribes a propósito, sino cuando PHP lo usa por ti:

**`switch` usa comparación suelta.** Esto era una trampa en PHP 7:

```php
$valor = 0;

switch ($valor) {
    case "admin":   // PHP 7: 0 == "admin" era true → ¡entraba aquí!
        echo "es admin";
        break;
    default:
        echo "otro valor";
}
```

En PHP 7 ese `switch` caía en `"admin"` por la conversión de tipos. Para evitarlo, usa `match` (PHP 8+), que compara con `===`:

```php
$resultado = match ($valor) {
    "admin" => "es admin",
    default => "otro valor",  // 0 nunca coincide con "admin"
};
```

**`in_array()` y `array_search()` comparan con `==` por defecto.** Pásales `true` como tercer argumento para forzar comparación estricta:

```php
$roles = ['admin', 'editor'];

var_dump(in_array(0, $roles));        // PHP 7: true (¡bug!) | PHP 8: false
var_dump(in_array(0, $roles, true));  // false siempre — usa ===
```

Acostúmbrate a pasar el `true`: es la versión segura.

## Comparar arrays y objetos

Con tipos compuestos, la diferencia entre `==` y `===` tiene matices propios.

**Arrays:**

```php
$a = ['x' => 1, 'y' => 2];
$b = ['y' => 2, 'x' => 1]; // mismas claves/valores, distinto orden

var_dump($a == $b);   // true  — mismos pares clave/valor (el orden no importa)
var_dump($a === $b);  // false — el orden de las claves difiere
```

Con `===`, dos arrays son idénticos solo si tienen los **mismos pares clave/valor, en el mismo orden y del mismo tipo**.

**Objetos:**

```php
class Punto {
    public function __construct(public int $x, public int $y) {}
}

$p1 = new Punto(1, 2);
$p2 = new Punto(1, 2);
$p3 = $p1;

var_dump($p1 == $p2);   // true  — misma clase y mismos atributos
var_dump($p1 === $p2);  // false — son dos instancias distintas
var_dump($p1 === $p3);  // true  — $p3 es la misma instancia que $p1
```

Para objetos, `==` compara clase y atributos; `===` exige que sean **la misma instancia** en memoria.

## Cuándo usar cada uno

- **`===` por defecto.** Es predecible, evita los bugs de conversión y deja la intención clara. En la práctica, es lo que quieres el 95% de las veces.
- **`==` solo cuando la conversión de tipos es intencional** y la entiendes bien (por ejemplo, comparar un valor de formulario que llega como string contra un número). Aun así, casi siempre es más limpio convertir el tipo de forma explícita y usar `===`.

## Preguntas frecuentes

### ¿Cuál es la diferencia entre `==` y `===` en PHP?

`==` compara solo el valor, convirtiendo los tipos si hace falta (`5 == "5"` es `true`). `===` compara valor **y** tipo, sin conversión (`5 === "5"` es `false`). Usa `===` por defecto para evitar bugs de conversión de tipos.

### ¿Por qué `0 == "texto"` daba `true` en PHP 7?

Porque PHP 7 convertía la string no numérica a `0` antes de comparar, así que quedaba `0 == 0`. PHP 8 cambió ese comportamiento: ahora convierte el número a string, y `0 == "texto"` es `false`.

### ¿Es seguro usar `in_array()`?

Por defecto no, porque compara con `==`. Pasa `true` como tercer argumento (`in_array($valor, $array, true)`) para que use comparación estricta y evites coincidencias inesperadas.

### ¿`===` es más rápido que `==`?

Marginalmente, porque se salta la conversión de tipos, pero la diferencia es insignificante. Elige el operador por corrección, no por velocidad: `===` gana por ser predecible, no por rendimiento.

## Cierre

La diferencia entre `==` y `===` se reduce a una sola idea: `===` también compara el tipo, `==` no. Como `==` puede convertir tipos por detrás —y PHP lo usa en `switch`, `in_array()` y más—, lo seguro es usar `===` por defecto y reservar `==` para los pocos casos donde la conversión es justo lo que buscas. Para repasar el resto de comparadores y operadores del lenguaje, vuelve a la [guía de operadores en PHP](/post/operadores-php).

---

## Sitemap

Índice completo del sitio: [/sitemap.md](https://www.angelcruz.dev/sitemap.md)

Canónico HTML: [https://www.angelcruz.dev/post/igual-vs-identico-php](https://www.angelcruz.dev/post/igual-vs-identico-php)
