Dans cet article
- La fonction empty() considère 7 valeurs différentes comme vides, ce qui provoque des bugs subtils
- La valeur 0 (zéro) est traitée comme vide par empty(), un piège fréquent en production
- Les alternatives recommandées sont isset(), is_null() et les comparaisons strictes selon le contexte
- Depuis PHP 8.x, l’opérateur nullsafe et les types stricts réduisent considérablement le besoin d’utiliser empty()
- Un tableau comparatif détaille les résultats de empty(), isset() et is_null() sur chaque type de valeur
- Je vous propose 5 règles concrètes pour remplacer empty() dans vos projets existants sans tout casser
Sommaire
- Qu’est-ce que empty() en PHP et comment fonctionne-t-elle ?
- Les 7 valeurs considérées comme vides par empty()
- Le piège du zéro et de la chaîne vide
- Différence entre empty(), isset() et is_null()
- Quand et par quoi remplacer empty()
- empty() dans PHP 8.x : ce qui change
- Bonnes pratiques pour vos projets PHP
En tant que formatrice BTS SIO, je vois chaque année des étudiants découvrir empty() en PHP et l’utiliser partout dans leur code. La fonction semble pratique : elle vérifie si une variable est « vide » en une seule ligne. Pourtant, après 12 ans de développement web, je peux vous affirmer que empty() est l’une des sources de bugs les plus sournoises du langage. Le problème ne vient pas de la fonction elle-même, mais de sa définition très large de ce qui est « vide ». Avant de l’utiliser dans votre prochain projet, prenons le temps de comprendre exactement ce qu’elle fait, ce qu’elle ne fait pas, et quelles alternatives privilégier.
Qu’est-ce que empty() en PHP et comment fonctionne-t-elle ?
La fonction empty() est un construct de langage PHP (et non une fonction à proprement parler) qui détermine si une variable est considérée comme « vide ». Sa syntaxe est simple :
empty(mixed $var): bool
Elle retourne true si la variable n’existe pas ou si sa valeur est équivalente à false. Elle retourne false dans tous les autres cas. Un point important : empty() ne génère jamais de warning, même si la variable n’a pas été déclarée. C’est d’ailleurs souvent la raison pour laquelle les développeurs l’utilisent à la place d’un simple test conditionnel.
// Pas de warning même si $variable n'existe pas
if (empty($variable)) {
echo 'La variable est vide ou non définie';
}
// Ceci génère un warning E_NOTICE si $variable n'existe pas
if (!$variable) {
echo 'La variable est falsy';
}
Concrètement, empty($var) est l’équivalent de !isset($var) || $var == false. Cette équivalence est la clé pour comprendre tous les pièges que nous allons explorer. La comparaison faible (==) avec false est précisément ce qui rend empty() si imprévisible pour les développeurs qui ne maîtrisent pas le typage en PHP.

Les 7 valeurs considérées comme vides par empty()
Pour utiliser empty() correctement, il faut connaître exhaustivement les valeurs qu’elle considère comme vides. En voici la liste complète :
// Toutes ces expressions retournent true
empty(""); // chaîne vide
empty(0); // entier zéro
empty(0.0); // flottant zéro
empty("0"); // chaîne "0"
empty(null); // null
empty(false); // booléen false
empty([]); // tableau vide
Cette liste pose un problème fondamental : elle mélange des concepts sémantiquement très différents. Une chaîne vide et la valeur null n’ont pas du tout la même signification dans un programme. La chaîne "0" n’est pas « vide » au sens intuitif du terme ; c’est un caractère parfaitement valide. Le zéro entier est une valeur numérique légitime, pas l’absence de valeur.
J’insiste sur ce point auprès de mes étudiants en BTS SIO option SLAM : quand vous écrivez empty($prix), vous traitez un article gratuit (prix à 0) exactement comme un article sans prix défini. Dans un contexte e-commerce, la différence est critique.
Pour les variables non déclarées, empty() se comporte également de manière spécifique :
// $nonDeclaree n'existe pas
var_dump(empty($nonDeclaree)); // true, sans warning
var_dump(isset($nonDeclaree)); // false, sans warning
var_dump($nonDeclaree); // NULL + E_WARNING
Cette suppression silencieuse des erreurs est à double tranchant. Elle peut masquer de vraies fautes de frappe dans les noms de variables, rendant le débogage bien plus difficile. Un empty($untilisateur) au lieu de empty($utilisateur) passera inaperçu pendant des semaines.
Le piège du zéro et de la chaîne vide
C’est le piège le plus fréquent et le plus documenté. En PHP, 0 est considéré comme empty, tout comme la chaîne "0". Ce comportement est cohérent avec le type juggling de PHP, mais il surprend régulièrement les développeurs.
Voici un exemple concret que j’utilise en cours :
// Formulaire de commande : quantité saisie par l'utilisateur
$quantite = $_POST['quantite'] ?? null;
if (empty($quantite)) {
echo 'Veuillez saisir une quantité';
// BUG : si l'utilisateur saisit 0, ce message s'affiche !
}
// Formulaire de notation : note sur 10
$note = $_POST['note']; // L'utilisateur a mis 0
if (empty($note)) {
echo 'Veuillez saisir une note';
// BUG : la note 0 est une note valide !
}
Le même problème se pose avec les chaînes numériques. Quand un formulaire HTML envoie des données, tout arrive sous forme de chaîne. La chaîne "0" est considérée comme vide par empty(), ce qui peut invalider des saisies parfaitement légitimes :
$codePostal = "0"; // Un code postal peut commencer par 0
var_dump(empty($codePostal)); // true !
$etage = "0"; // Rez-de-chaussée
var_dump(empty($etage)); // true !
La solution correcte dépend de votre intention réelle. Si vous voulez vérifier qu’une chaîne de formulaire a été remplie, utilisez une comparaison stricte :
// Vérifier qu'un champ de formulaire est rempli
if (!isset($_POST['quantite']) || $_POST['quantite'] === '') {
echo 'Champ requis';
}
// Ou avec le null coalescing + comparaison stricte
$quantite = $_POST['quantite'] ?? '';
if ($quantite === '') {
echo 'Champ requis';
}
Si vous manipulez des dates ou des valeurs numériques issues de formulaires, cette distinction est d’autant plus importante. Un champ date vide et un champ date contenant « 0 » ne doivent pas être traités de la même façon.

Différence entre empty(), isset() et is_null()
Pour choisir la bonne fonction, il faut comprendre ce que chacune teste réellement. Voici un tableau comparatif complet qui résume le comportement de ces trois fonctions sur chaque type de valeur :
| Valeur testée | empty() | isset() | is_null() | == false |
|---|---|---|---|---|
"" (chaîne vide) |
true | true | false | true |
0 (entier) |
true | true | false | true |
0.0 (flottant) |
true | true | false | true |
"0" (chaîne) |
true | true | false | true |
null |
true | false | true | true |
false |
true | true | false | true |
[] (tableau vide) |
true | true | false | true |
"hello" |
false | true | false | false |
1 |
false | true | false | false |
" " (espace) |
false | true | false | false |
| Variable non déclarée | true | false | Warning + true | Warning + true |
Quelques observations essentielles à tirer de ce tableau :
- isset() teste uniquement si la variable existe ET n’est pas null. C’est la fonction la plus précise pour vérifier l’existence d’une variable.
- is_null() teste uniquement si la valeur est strictement null. Attention, elle génère un warning si la variable n’existe pas.
- empty() est le test le plus large : il combine l’absence de la variable ET la « falsyness » de sa valeur.
En pratique, la question que vous devez vous poser est : que voulez-vous réellement tester ?
// "La variable existe-t-elle ?" → isset()
if (isset($_GET['page'])) { /* ... */ }
// "La variable est-elle null ?" → === null ou is_null()
if ($result === null) { /* ... */ }
// "La chaîne est-elle vide ?" → === ''
if ($nom === '') { /* ... */ }
// "Le tableau est-il vide ?" → === [] ou count() === 0
if ($items === []) { /* ... */ }
// "La variable existe ET a une valeur non-falsy ?" → empty()
// C'est le seul cas où empty() est vraiment pertinent
if (!empty($options)) { /* ... */ }
Si vous travaillez avec des requêtes SQL et que vous devez distinguer les valeurs NULL d’une base de données, l’utilisation d’empty() est particulièrement risquée. Un COUNT retournant 0 n’est pas la même chose qu’un résultat NULL.
Quand et par quoi remplacer empty()
Je ne suis pas de ceux qui disent « n’utilisez jamais empty() ». Mon approche est plus pragmatique : utilisez empty() uniquement quand son comportement large est exactement ce que vous voulez. Dans tous les autres cas, préférez des tests explicites.
Voici les alternatives recommandées selon le contexte :
Vérifier un paramètre de requête HTTP
// ❌ Piégeux : 0 est une valeur valide pour une page
if (empty($_GET['page'])) {
$page = 1;
}
// ✅ Explicite et correct
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
// ✅ PHP 7+ avec null coalescing
$page = (int)($_GET['page'] ?? 1);
Vérifier qu’une chaîne est remplie
// ❌ "0" sera rejeté
if (empty($nom)) {
throw new InvalidArgumentException('Nom requis');
}
// ✅ Comparaison stricte
if ($nom === '' || $nom === null) {
throw new InvalidArgumentException('Nom requis');
}
// ✅ Avec trim pour les espaces
if (trim($nom) === '') {
throw new InvalidArgumentException('Nom requis');
}
Vérifier qu’un tableau contient des éléments
// ⚠️ Fonctionne, mais peu lisible sur l'intention
if (empty($resultats)) {
echo 'Aucun résultat';
}
// ✅ L'intention est claire
if (count($resultats) === 0) {
echo 'Aucun résultat';
}
// ✅ Encore plus explicite
if ($resultats === []) {
echo 'Aucun résultat';
}
Pour les tableaux, j’admets qu’empty() est acceptable. Un tableau vide n’a pas l’ambiguïté du zéro ou de la chaîne « 0 ». C’est l’un des rares cas où je ne corrige pas mes étudiants quand ils l’utilisent.
Vérifier une valeur numérique
// ❌ 0 et 0.0 sont des valeurs numériques valides
if (empty($prix)) {
echo 'Prix non défini';
}
// ✅ Distinguer l'absence de valeur de la valeur zéro
if ($prix === null) {
echo 'Prix non défini';
} elseif ($prix === 0 || $prix === 0.0) {
echo 'Article gratuit';
}
Ces patterns sont particulièrement utiles quand vous manipulez des chaînes de caractères extraites de formulaires, où la distinction entre « non rempli » et « rempli avec zéro » est capitale.

empty() dans PHP 8.x : ce qui change
Avec l’arrivée de PHP 8.0, 8.1, 8.2 et 8.3, plusieurs fonctionnalités réduisent considérablement le besoin d’utiliser empty(). Le langage offre désormais des outils plus précis pour gérer les valeurs nulles et les types.
L’opérateur nullsafe (?->)
// Avant PHP 8.0 : on utilisait empty() pour éviter les erreurs
if (!empty($user) && !empty($user->getAddress())) {
$city = $user->getAddress()->getCity();
}
// PHP 8.0+ : l'opérateur nullsafe gère tout
$city = $user?->getAddress()?->getCity();
Les types union et nullable
// PHP 8.0+ : le type indique explicitement si null est possible
function getUsername(?string $input): string
{
// Pas besoin de empty(), le type garantit que $input
// est soit une string, soit null
if ($input === null || $input === '') {
return 'Anonyme';
}
return $input;
}
Les propriétés typées
class Product
{
// PHP 8.1+ : la propriété DOIT être initialisée
public readonly string $name;
public readonly float $price;
// Plus besoin de vérifier si $product->name est "empty"
// Le type system garantit qu'il contient une string valide
}
La fonction str_contains() et ses sœurs
PHP 8.0 a introduit str_contains(), str_starts_with() et str_ends_with(). Ces fonctions rendent obsolètes certains usages d’empty() combiné à strpos() :
// Avant : piège classique car strpos retourne 0 (position) pour une correspondance en début de chaîne
if (!empty(strpos($haystack, $needle))) { /* BUG si trouvé en position 0 */ }
// PHP 8.0+ : plus de piège
if (str_contains($haystack, $needle)) { /* correct */ }
En résumé, plus votre code utilise les fonctionnalités modernes de PHP, moins vous aurez besoin d’empty(). Les enums PHP remplacent également certains cas où l’on testait si une valeur de configuration était vide : un enum typé ne peut tout simplement pas être « vide ».
Bonnes pratiques pour vos projets PHP
Après des années de formation et de développement, voici les 5 règles que j’applique systématiquement dans mes projets et que je recommande à mes étudiants :
Règle 1 : posez-vous la question « que dois-je réellement tester ? »
Avant d’écrire empty($var), formulez précisément votre intention. Voulez-vous savoir si la variable existe ? Si elle est null ? Si la chaîne est vide ? Si le nombre est zéro ? Chaque intention a sa propre expression en PHP, et cette expression est presque toujours plus claire qu’empty().
Règle 2 : activez le typage strict
declare(strict_types=1);
Avec le typage strict activé, PHP refuse les conversions implicites de types. Cela rend empty() encore moins pertinent car vos fonctions reçoivent des types prévisibles. Si une fonction attend un string, vous savez qu’elle ne recevra jamais un int ou un null (sauf si le type est ?string).
Règle 3 : utilisez les outils d’analyse statique
Des outils comme PHPStan (niveau 6+) et Psalm signalent les usages dangereux d’empty(). PHPStan propose même une règle spécifique DisallowedEmptyRule pour interdire empty() dans votre base de code. Intégrez ces vérifications dans votre pipeline CI/CD pour attraper les problèmes avant qu’ils n’atteignent la production.
Règle 4 : acceptez empty() pour les tableaux et les vérifications d’existence
Je ne suis pas dogmatique. empty($array) est parfaitement lisible et sans ambiguïté pour vérifier qu’un tableau est vide. De même, !empty($_POST['field']) est un raccourci raisonnable quand vous voulez simplement savoir si un champ de formulaire a été soumis avec une valeur non vide, et que zéro n’est pas une valeur attendue.
Règle 5 : documentez vos choix dans le code
// Si vous utilisez volontairement empty(), un commentaire aide :
// empty() voulu ici : on veut rejeter '', 0, null et false
if (empty($config['debug_mode'])) {
$debug = false;
}
Pour organiser votre code de manière cohérente, pensez aussi à vos requêtes SQL. Un ORDER BY bien structuré évite de devoir tester des résultats « vides » côté PHP. De même, les LEFT JOIN avec WHERE doivent être pensés pour retourner des résultats prévisibles, réduisant le besoin de tests défensifs avec empty().
Pour les projets qui utilisent des frameworks modernes comme Laravel ou Symfony, la plupart des validations de formulaire sont gérées par des validators dédiés. Vous n’avez plus besoin d’écrire if (empty($request->input('email'))) car le framework s’en charge avec des règles comme 'email' => 'required|email'. La fonction count() reste toutefois utile pour vérifier le nombre d’éléments retournés par une requête.
Enfin, pensez à la lisibilité pour votre équipe. Un code qui utilise des comparaisons explicites est plus facile à relire, à déboguer et à maintenir. Quand un nouveau développeur lit $name !== '', il comprend immédiatement l’intention. Quand il lit !empty($name), il doit connaître la liste complète des valeurs « empty » pour savoir ce qui est réellement testé. Les commentaires dans le code ne remplacent jamais un code auto-documenté.
À retenir
- Remplacez empty($var) par une comparaison stricte (
=== '',=== null,=== []) adaptée à votre intention réelle - Méfiez-vous du piège 0 et « 0 » considérés comme vides : utilisez
=== nullpour les valeurs numériques optionnelles - Activez declare(strict_types=1) dans tous vos fichiers PHP pour réduire les conversions implicites
- Réservez empty() aux tableaux et aux vérifications d’existence de clés dans
$_GETou$_POSTquand zéro n’est pas une valeur valide - Intégrez PHPStan niveau 6+ dans votre CI/CD pour détecter automatiquement les usages dangereux d’empty()
Questions fréquentes
What is empty() in PHP ?
La fonction empty() est un construct de langage PHP qui teste si une variable est considérée comme « vide ». Elle retourne true pour 7 valeurs : la chaîne vide "", l’entier 0, le flottant 0.0, la chaîne "0", null, false et le tableau vide []. Elle retourne également true si la variable n’a pas été déclarée, sans générer de warning. Son fonctionnement est équivalent à !isset($var) || $var == false.
Est-ce que null est la même chose que empty en PHP ?
Non, null et empty sont deux concepts différents. null est une valeur spécifique qui signifie « aucune valeur ». La fonction empty() retourne true pour null, mais aussi pour 6 autres valeurs (0, 0.0, « », « 0 », false, []). Tester empty($var) ne revient donc pas à tester $var === null. Si vous voulez vérifier qu’une variable est spécifiquement null, utilisez is_null() ou la comparaison stricte === null.
Est-ce que 0 est considéré comme empty en PHP ?
Oui, 0 est considéré comme empty en PHP. Cela vaut pour l’entier 0, le flottant 0.0 et même la chaîne "0". C’est l’un des pièges les plus fréquents : si vous testez empty($prix) et que le prix vaut 0 (article gratuit), empty() retournera true. Pour éviter ce problème, utilisez une comparaison stricte comme $prix === null pour tester l’absence de valeur, ou $prix === 0 pour tester spécifiquement le zéro.
Quelle est la différence entre isset() et empty() en PHP ?
isset() vérifie uniquement si une variable existe et n’est pas null. empty() vérifie si une variable n’existe pas OU si sa valeur est « falsy » (équivalente à false). Par exemple, pour la valeur 0 : isset() retourne true (la variable existe), tandis que empty() retourne true (la valeur est considérée comme vide). Pour null : isset() retourne false, empty() retourne true. Utilisez isset() quand vous testez l’existence, empty() quand vous testez l’existence ET la « valeur ».
Comment tester si une chaîne est vide en PHP sans utiliser empty() ?
Pour tester si une chaîne est vide sans les effets de bord d’empty(), utilisez la comparaison stricte : $chaine === ''. Si vous voulez aussi gérer les espaces, combinez avec trim() : trim($chaine) === ''. Pour vérifier qu’une variable chaîne existe et n’est pas vide, utilisez isset($chaine) && $chaine !== ''. Ces alternatives sont plus explicites et ne traitent pas la valeur "0" comme vide, contrairement à empty().
Peut-on utiliser empty() avec des expressions en PHP ?
Depuis PHP 5.5, oui. Avant cette version, empty() n’acceptait que des variables. Depuis PHP 5.5, vous pouvez écrire empty(trim($input)) ou empty($obj->getMethod()). Cependant, dans ce cas, l’avantage principal d’empty() (ne pas générer de warning pour les variables non définies) disparaît, car les expressions génèrent des erreurs normalement. Il est alors souvent plus lisible d’utiliser directement une comparaison explicite.
Formatrice IT indépendante depuis 2016, ancienne étudiante BTS SIO SLAM. 6 ans d'expérience en entreprise.