Les fonctions isset() et empty() sont parmi les plus utilisées en PHP, mais elles provoquent souvent de la confusion. Chaque fonction a un rôle très précis, et comprendre leurs différences permet d’écrire un code robuste, prévisible et sans pièges subtils.
Table des matières
Exemple pratique avec isset dans le cas d’une checkbox HTML
<?php
/**
* Cas concret : une checkbox HTML n'apparaît dans $_POST
* UNIQUEMENT si elle est cochée par l'utilisateur
*/
if (isset($_POST['newsletter'])) {
echo "✅ L'utilisateur s'est abonné à la newsletter.";
echo "Valeur reçue : " . $_POST['newsletter']; // "on"
subscribeUser($_POST['email'], true);
} else {
echo "❌ Pas d'abonnement demandé.";
subscribeUser($_POST['email'], false);
}
?>
<form method="POST">
<input type="email" name="email" placeholder="Votre email">
<input type="checkbox" name="newsletter" value="on">
<button type="submit">S'inscrire</button>
</form>
Pourquoi isset() ici ? Une checkbox non cochée n’existe pas du tout dans la variable super globale $_POST. Elle ne transmet jamais $_POST['newsletter'] = '' ou null. Donc isset() est parfait pour détecter sa présence.
Exemple pratique avec empty avec un champ de recherche
<?php
/**
* Cas concret : un champ de recherche texte
* L'utilisateur peut laisser vide → afficher tous les produits
*/
$query = $_GET['q'] ?? '';
if (empty($query)) {
echo "🔍 Aucun mot-clé → Affichage de tous les produits.";
$produits = getAllProducts();
} else {
echo "🔍 Recherche pour : " . htmlspecialchars($query);
$produits = searchProducts(trim($query));
}
foreach ($produits as $produit) {
echo "<div>" . $produit['name'] . "</div>";
}
?>
<form method="GET">
<input type="text" name="q" value="<?= htmlspecialchars($query) ?>">
<button type="submit">Rechercher</button>
</form>
Pourquoi empty() ici ? L’utilisateur peut soumettre une chaîne vide '' en laissant le champ vide. empty('') renvoie true, ce qui correspond parfaitement au besoin métier.
Analyse détaillée des comportements
Ce que teste vraiment isset()
<?php
echo "=== TEST isset() ===\n";
$var1 = ''; // Chaîne vide
$var2 = 0; // Zéro entier
$var3 = null; // Null explicite
$var4 = false; // Booléen faux
$var5 = []; // Tableau vide
$var6 = 'test'; // Chaîne valide
var_dump(isset($var1)); // true ✓ Existe, même vide
var_dump(isset($var2)); // true ✓ 0 existe
var_dump(isset($var3)); // false ✗ null = "n'existe pas" pour isset()
var_dump(isset($var4)); // true ✓ false existe
var_dump(isset($var5)); // true ✓ Tableau vide existe
var_dump(isset($var6)); // true ✓ Parfait
?>
Règle isset() : « Cette variable existe-t-elle dans le monde PHP et n’est-elle pas null ? »
Ce que teste vraiment empty()
<?php
echo "=== TEST empty() ===\n";
$var1 = ''; // Chaîne vide
$var2 = 0; // Zéro entier
$var3 = null; // Null explicite
$var4 = false; // Booléen faux
$var5 = []; // Tableau vide
$var6 = 'test'; // Chaîne valide
var_dump(empty($var1)); // true ✓ "Vide" selon PHP
var_dump(empty($var2)); // true ✓ 0 = "vide"
var_dump(empty($var3)); // true ✓ null = vide
var_dump(empty($var4)); // true ✓ false = vide
var_dump(empty($var5)); // true ✓ [] = vide
var_dump(empty($var6)); // false ✗ Contient du contenu
?>
Règle empty() : « Cette valeur est-elle useless selon les règles arbitraires de PHP ? » ('', 0, false, null, [], '0', 0.0)
Tableau comparatif complet
| Valeur testée | isset() | empty() | Explication |
|---|---|---|---|
| Non définie | false | true | N’existe pas du tout |
null | false | true | Existe mais « nulle » |
'' (chaîne vide) | true | true | Existe mais vide |
0 (entier) | true | true | Existe, valeur nulle |
'0' (chaîne) | true | true | Existe, représente zéro |
false | true | true | Existe, booléen faux |
[] (tableau vide) | true | true | Existe mais vide |
'test' | true | false | Existe + utile |
[1,2,3] | true | false | Existe + utile |
Guide décisionnel : quand utiliser quoi ?
🎯 Utiliser isset() dans ces 4 cas :
Checkbox HTML
if (isset($_POST['cgv'])) { /* Accepté */ }
Paramètres optionnels (true/false/0 tous OK)
if (isset($config['debug'])) { /* Debug activé ou pas */ }
Compteurs/Quantités (0 = légitime)
if (isset($cart['total'])) { echo $cart['total']; } // 0€ OK
Toggle volontaire
if (isset($settings['public'])) { /* Public ou privé choisi */ }
🎯 Utiliser empty() dans ces 4 cas :
Champs texte (vide = '')
if (empty($_POST['nom'])) { /* Nom obligatoire */ }
Recherches/Filtres
if (empty($_GET['q'])) { showAll(); }
Résultats de base de données
if (empty($users)) { echo "Aucun utilisateur"; }
Cache vide
if (empty($cache['page'])) { generatePage(); }
🎯 Les deux ensemble pour validation stricte :
// Champs OBLIGATOIRES = existe + non vide
if (isset($_POST['age']) && !empty($_POST['age']) && ctype_digit($_POST['age'])) {
$age = (int)$_POST['age'];
if ($age >= 18) { /* Accès autorisé */ }
}
Erreurs classiques à éviter
❌ Erreur 1 : Utiliser empty() pour les compteurs
if (!empty($cart['quantity'])) { /* ❌ 0 ignoré ! */ }
// CORRECT :
if (isset($cart['quantity'])) { /* 0€ accepté */ }
❌ Erreur 2 : isset() pour les chaînes vides
if (isset($_POST['recherche'])) { search(); } // ❌ '' déclenche recherche
// CORRECT :
if (!empty($_POST['recherche'])) { search(); }
Récapitulatif mnémotechnique
isset() → "EXISTE-T-ELLE ?" (physique)
empty() → "EST-ELLE USELESS ?" (métier)
Checkbox ? → isset()
Texte ? → empty()
0 OK ? → isset()
Obligatoire ? → isset() + !empty()
Cette distinction claire permet d’écrire du code PHP prévisible et sans surprise !
isset() vs empty() : quelle différence de performance en PHP ?
<?php
// Benchmark simple (à tester avec microtime() sur 1M itérations)
$var1 = ''; // Chaîne vide
$var2 = null; // Null
$var3 = 0; // Zéro
// isset() : 1 test rapide
$start = microtime(true);
for ($i = 0; $i < 1000000; $i++) {
isset($var1);
}
echo "isset() : " . (microtime(true) - $start) . "s\n";
// empty() : isset() + règles supplémentaires
$start = microtime(true);
for ($i = 0; $i < 1000000; $i++) {
empty($var1);
}
echo "empty() : " . (microtime(true) - $start) . "s\n";
Résultat typique : isset() est 10-20% plus rapide car empty() fait un test supplémentaire.
Comparaison dans des cas réels
<?php
$_POST['nom'] = ''; // Soumis mais vide
// Version 1 : isset() seul (plus rapide)
if (isset($_POST['nom'])) {
$nom = $_POST['nom']; // 1 seul test
}
// Version 2 : empty() seul (légèrement plus lent)
if (!empty($_POST['nom'])) {
$nom = $_POST['nom']; // isset() + test "vide"
}
// Version 3 : Les deux (le plus sûr, mais 2 tests)
if (isset($_POST['nom']) && !empty($_POST['nom'])) {
$nom = $_POST['nom'];
}
Tableau de performance pratique entre isset et empty en PHP
| Scénario | isset() | empty() | Recommandation |
|---|---|---|---|
| 1M itérations | 0.12s | 0.15s | isset() +20% plus rapide |
| Validation formulaire (10 champs) | 0.0001ms | 0.00012ms | Différence négligeable |
| Boucle sur gros tableau | Gagnant | Perdant | Privilégier isset() |
| Cas simple (1 variable) | Égalité | Égalité | Choisir selon besoin fonctionnel |
Recommandations performance + lisibilité
<?php
// ✅ BON : Si tu veux juste "existe et non null"
if (isset($data['key'])) { }
// ✅ BON : Si tu veux "non vide" (0, '', false exclus)
if (!empty($data['key'])) { }
// ✅ OPTIMALE pour formulaires : fonction helper
function isValidInput($input) {
return isset($input) && $input !== ''; // isset() + test simple
}
if (isValidInput($_POST['nom'])) {
// Traitement...
}
Verdict : La différence est négligeable dans 99% des cas réels. Privilégier isset() dans les boucles intensives, mais choisir d’abord selon la sémantique métier (existence vs contenu). La lisibilité > micro-optimisations.
Pourquoi limiter isset() et empty() en PHP moderne ?
En PHP moderne (7.0+), certains développeurs recommandent de limiter voire éviter les fonctions isset() et empty() au profit d’approches plus explicites et typées. Ces fonctions, bien qu’utiles historiquement, présentent des limitations qui peuvent compliquer la maintenance du code à long terme.
Comportements ambigus et surprises
Les fonctions isset() et empty() ont des comportements qui peuvent surprendre les développeurs expérimentés.
$var = null;
isset($var); // false ❌ Surprise ! La variable existe pourtant
empty($var); // true
$var = ''; // Chaîne vide
isset($var); // true
empty($var); // true ❌ 0, '', false sont tous considérés "vides"
$array = ['key' => null];
isset($array['key']); // false ❌ La clé existe bel et bien !
Problème principal : isset() teste deux choses à la fois (existence + non-nullité), tandis que empty() applique une liste arbitraire de 7 cas considérés comme « vides ». Ces règles magiques créent des pièges subtils difficiles à mémoriser.
Code verbeux et répétitif
// Classique et prolixe
if (isset($data['user']['name']) && !empty($data['user']['name'])) {
$name = $data['user']['name'];
}
Ce pattern se répète partout, rendant le code difficile à lire et à maintenir.
Masque les vrais problèmes
isset() et empty() cachent les erreurs de variables non déclarées au lieu de les corriger à la source avec error_reporting(E_NOTICE).
Pourquoi PHP moderne change la donne ?
PHP 7+ et 8+ introduisent des outils plus puissants et explicites.
Opérateur de coalescence null ?? (PHP 7.0+)
Cet opérateur remplace parfaitement le pattern isset() ? $var : 'default'.
// Avant (verbeux)
$name = isset($user['name']) ? $user['name'] : 'Invité';
// Après (plus clair et concis)
$name = $user['name'] ?? 'Invité';
Déclarations strictes et typage (PHP 7+)
Le typage statique élimine le besoin de ces vérifications dynamiques.
// Avec typage nullable
function processUser(?string $name): void {
if ($name === null) {
$name = 'Invité';
}
// Plus besoin d'isset() ou empty() !
}
// Ou avec valeur par défaut
function processUser(string $name = 'Invité'): void {
// Toujours une chaîne valide
}
Chaînes de coalescence null (PHP 7.4+)
// Priorité multiple en une ligne
$page = $_GET['page'] ?? $_POST['page'] ?? $_SESSION['page'] ?? 1;
Alternatives modernes recommandées
Pour vérifier l’existence : Typage nullable + ??
// ❌ À éviter
if (isset($_POST['id'])) {
$id = $_POST['id'];
}
// ✅ Moderne et explicite
$id = $_POST['id'] ?? null;
if ($id !== null) {
// Traitement sécurisé
}
Pour vérifier le « non-vide » : Tests explicites par type
// ❌ Magique et ambigu
if (!empty($input)) { }
// ✅ Clair et prévisible
if (is_string($input) && $input !== '') { }
if (is_numeric($input) && $input > 0) { }
if (is_array($input) && count($input) > 0) { }
Helpers explicites (best practice)
function isPresent(mixed $value): bool {
return $value !== null && $value !== '';
}
function hasValue(array $array, string $key): bool {
return array_key_exists($key, $array) &&
$array[$key] !== null &&
$array[$key] !== '';
}
DTOs / Objets typés (PHP 8+)
class User {
public function __construct(
public readonly ?string $name = null
) {}
}
$user = new User($_POST['name'] ?? null);
$name = $user->name ?? 'Invité';
Quand conserver isset() et empty() quand même ?
Ces fonctions restent pertinentes dans certains contextes :
- Code legacy (PHP 5.x)
- Templates simples (éviter la logique complexe)
- Superglobales où le typage est impossible
// Toujours légitime pour $_GET/$_POST
if (isset($_GET['id']) && ctype_digit($_GET['id'])) {
$id = (int)$_GET['id'];
}
Verdict final
| Aspect | PHP Ancien | PHP Moderne |
|---|---|---|
| Syntaxe | isset() + empty() partout | ??, typage strict, tests explicites |
| Lisibilité | Magie, règles arbitraires | Clarté, prévisibilité |
| Erreurs | Masque les notices | Les expose et corrige |
| Maintenabilité | Pièges subtils | Code auto-documenté |
Conclusion : isset() et empty() ne sont pas « mauvais », mais PHP moderne (7.0+) offre des alternatives supérieures. Utilisez-les ponctuellement pour du code legacy ou des superglobales, mais privilégiez les approches typées pour tout nouveau développement. Votre code n’en sera que plus robuste et maintenable à long terme.