Foire Aux Questions PHP

Erreurs, pages blanches, PHP pas interprété, caractères spéciaux, accents, encodage, é, �, etc.

a marqué ce sujet comme résolu.

Reprise du dernier message de la page précédente

Comment vérifier la validité du domaine d’une adresse email ?

Là aussi, vous pouvez vous aider de ceci, qui se base sur la fonction checkdnsrr() :

<?php
function verif_email($email) {
    // On scinde l'adresse au niveau de la première arobase (s'il y en a deux…)
    list($user, $domaine) = explode('@', $email, 2);
    // On vérifie qu'il y a un enregistrement MX (Mail eXchange) pour le domaine
    return checkdnsrr($domaine, "MX");
}

if (verif_email('zestedesavoir@hotmail.com')) {
    echo 'hotmail.com existe bien';
} else {
    echo 'hotmail.com n\'existe pas';
}
Fonction de vérification d’un enregistrement MX et exemple d’utilisation

hotmail.com existe bien

Résultat

La fonction checkdnsrr() n’était pas disponible sur système Windows avant PHP 5.3

Dans le cas où vous avez un environnement qui n’implémente pas cette fonction, vous pouvez la créer. La proposition ci-dessous ne retourne qu’un simple booléen, dans le but unique d’éviter la génération d’une erreur fatale du fait que la fonction n’existe pas.

<?php
if (!function_exists('checkdnsrr')) {
    function checkdnsrr() {
        return true;
    }
}
Alternative pour Windows sous PHP < 5.3

Édité par Ymox

Evitez qu’on vous dise de les lire : FAQ PHP et SymfonyTutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+0 -0

Comment passer plusieurs informations dans des champs de formulaires portant le même name lors d’une soumission ?

Simplement en indiquant que l’on passe un tableau, ce que les champs de formulaires gèrent nativement. On indique que des champs de formulaires font partie d’un tableau en ajoutant une paire de crochets dans la valeur de l’attribut name.

Dans le cas de séries de cases à cocher, seules les valeurs des éléments cochés seront envoyées. Ce qui implique que si aucune case n’est cochée, aucune valeur ne sera envoyée, et l’index correspondant dans $_POST n’existera pas — voir ce message

<form action="" method="post">
    <p>
        <input type="checkbox" name="plop[]" value="10" />
        <input type="checkbox" name="plop[]" value="20" />
    </p>
    <p>
        <button type="submit">Test</button>
    </p>
</form>
Exemple d’utilisation des crochets dans l’attribut name pour le cas de listes d’options

Le résultat de print_r($_POST['plop']) sera donc un tableau et vaudra, si les deux cases ont été cochées :

Array
(
    [0] => 10
    [1] => 20
)
Résultat de print_r($_POST['plop']) si les deux cases ont été cochées

Le résultat de print_r($_POST['plop']) vaudra, si seulement la seconde des deux cases a été cochée :

Array
(
    [0] => 20
)
Résultat de print_r($_POST['plop']) dans le cas où seule la seconde case a été cochée

Il est évidemment possible de le faire avec des champs ou l’attribut type est autre que checkbox. C’est aussi la manière de faire si vous utiliser l’attribut multiple de la balise <select>

Il est possible de spécifier des index directement dans les champs du formulaire, en les mettant entre les crochets bien entendu.

<input type="checkbox" name="questions[1][]" value="Oui" />
<textarea name="questions[commentaires]"></textarea>
Exemple d’index placés directement dans le HTML. Notez cependant que des index sous forme de chaîne n’ont pas besoin d’être entourés de guillemets, ni simples, ni doubles.

Exemple avec un système pour changer des états en gros (articles publiés ou non)

<?php
$sql = 'SELECT id, etat FROM uneTable ORDER BY id DESC';
$result = $pdo->query($sql);
echo '
<form action="" method="post">
<p>
';
while ($l = $result->fetch(PDO::FETCH_ASSOC)) {
    echo '<label for="' . $l['id'] . '">' . $l['id'] . '</label>';
    $checked = $l['etat'] == 1 ? ' checked="checked"' : '';
    echo '<input id="' . $l['id'] . '" type="checkbox" name="listeId[]"' . $checked . ' />';
}
echo '</p>
<p>
<button type="submit">Modifier les états"</button>
</p>
</form>';
Exemple avec des ids d’une table passées dans des cases à cocher, pour modification de l’état d’une colonne des lignes de la table

Que l’on pourrait traiter simplement par :

<?php
if (!empty($_POST['listeId']) && is_array($_POST['listeId'])) {
    $_POST['listeId'] = array_unique(array_map('intval', $_POST['listeId']));
    // Mise à l'état actif des ids reçus
    $sql = 'UPDATE uneTable SET etat=1 WHERE id IN(' . implode(',', $_POST['listeId']) . ')';
    $result = $pdo->exec($sql);
    // Mise à l'état inactif des ids non reçus
    $sql = 'UPDATE uneTable SET etat=0 WHERE id NOT IN(' . implode(',', $_POST['listeId']) . ')';
    $result = $pdo->exec($sql);
}
Exemple de traitement du formulaire proposé ci-dessus

Autre exemple avec un upload multiple

<?php
$nbChamp = 5;
// Ne pas omettre l'attribut enctype
echo '<form action="" method="post" enctype="multipart/form-data">';
for ($i=0; $i<$nbChamp; $i++) {
    echo '<p><input type="file" name="image[]" /></p>';
}
echo '<p>
<button type="submit">Téléverser les images"</button>
</p>
</form>';
Exemple de formulaire d’upload avec un champ par fichier

Que l’on pourrait vérifier avec :

<?php
if (!empty($_FILES['image']) && array_filter($_FILES['image']['tmp_name'])) {
    for ($nbImg = count($_FILES['image']['tmp_name']), $i = 0; $i < $nbImg; $i++) {
        // On fait nos vérifications et actions pour chaque images
        // Soit :
        // $_FILES['image']['name'][$i]
        // $_FILES['image']['tmp_name'][$i]
        // etc…
        // Faites un print_r($_FILES) pour visualiser comment se présente le tableau
    }
}
Exemple de traitement d’un formulaire d’upload multiple avec un champ par fichier

Édité par Ymox

Evitez qu’on vous dise de les lire : FAQ PHP et SymfonyTutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+0 -0

Mes cookies ne fonctionnent pas, quelles peuvent-en être les raisons ?

A savoir, un cookie n’est disponible uniquement après (re-)chargement d’une page, que ce soit la même ou une autre1

Par étape :

  • Vérifiez les options de votre navigateur : est-il configuré de façon à accepter les cookies2 ?
  • Toujours sur votre navigateur, vérifiez si oui ou non vos cookies y sont présents3
  • Vérifiez que vous avez bien spécifié une durée de vie du cookie correcte
    Elle doit être supérieure au timestamp actuel
  • Si vous créez vos cookies dans une page étant dans un sous-répertoire de votre site, et que vous en avez besoin dans une page située à sa racine, vous devez renseigner le 4ème argument de la fonction setCookie(). Dans le cas exposé, il faut y mettre un /4

  1. Et après avoir créé ledit cookie, bien entendu 

  2. Voir les options de votre navigateur 

  3. Idem 

  4. / désigne la racine du site 

Édité par Ymox

Evitez qu’on vous dise de les lire : FAQ PHP et SymfonyTutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+0 -0

Comment afficher la date au format français ?

Depuis PHP 5.3, il existe la classe DateTime qui, si vous avez intl et ICU disponibles et activées, peut être utilisée en conjonction avec la classe IntlDateFormatter

<?php
$now = new DateTime();
$metteurEnForme = new IntlDateFormatter(
    'fr',
    IntlDateFormatter::FULL,
    IntlDateFormatter::NONE
);
echo $metteurEnForme->format($now);
Exemple de génération d’une date au format français avec DateTime et IntlDateFormatter

Pour les versions plus vieilles ou sans intl ou/ni ICU, vous pouvez vous servir de la fonction setlocale()

Si vous devez travailler sous Windows avec PHP < 5.4, notez qu’il n’est pas possible d’utiliser de l’UTF-8 avec setLocale()

<?php
setlocale(LC_ALL, 'fr_FR.UTF8', 'fr_FR','fr','fr','fra','fr_FR@euro');
echo strftime("%A %d %B %Y");
Exemple de génération de date au format français avec la fonction strftime()
mardi 27 août 2013
Résultat (identique avec les deux solutions)

Édité par Ymox

Evitez qu’on vous dise de les lire : FAQ PHP et SymfonyTutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+0 -0

Je désire exécuter un script à intervalles réguliers (par exemple un backup de ma base de données, ou l'envoi de mails à un certain moment), comment faire ?

Vous pouvez premièrement vous tourner vers votre hébergeur pour savoir si ces tâches automatiques (appellées cron) ne sont pas déjà comprises dans votre plan d'hébergement.
Sinon, vous pouvez utiliser des services externes tels que Online Cron job (gratuit dans sa formule de base, mais imposant leur logo sur votre site) ou WebCron au prix de 0.0001 € par exécution.

Autre possibilité, pour des tâches ne nécessitant pas trop de ressources : vous préparez un script qui sera embarqué sur toutes les pages de votre application. Ce script va vérifier s'il doit lancer la tâche selon la dernière exécution.
Ainsi, ce seront les utilisateurs qui déclencheront l'exécution de la tâche.

Evitez qu’on vous dise de les lire : FAQ PHP et SymfonyTutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+0 -0

Comment obtenir l'URL du site d'où vient le visiteur ?

Cette information est contenue dans une variable superglobale : $_SERVER['HTTP_REFERER'] On peut donc faire comme ceci :

1
2
<?php
echo 'Vous venez du site : ' . htmlspecialchars($_SERVER['HTTP_REFERER']);

Exemple d'utilisation de $_SERVER['HTTP_REFERER']

Ne vous fiez pas à cette valeur : le visiteur peut refuser de fournir cette information ou la modifier

Evitez qu’on vous dise de les lire : FAQ PHP et SymfonyTutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+0 -0

Quelle est la différence entre == et === ?

== effectue une comparaison "paresseuse". Cette comparaison ne tient pas compte du type de ce qui est comparé : PHP va prendre les deux parties et les convertir en deux valeurs du même type pour voir si elles correspondent. Voici un tableau qui permet de voir ce qu’il en résulterait

$a == $b $b = '' $b = 1 $b = 0 $b = ' ' $b = 'a' $b = null $b = false $b = true
$a = '' true false true false false true true false
$a = 1 false true false false false false false true
$a = 0 true false true true true true true false
$a = ' ' false false true true false false false true
$a = 'a' false false true false true false false true
$a = null true false true false false true true false
$a = false true false true false false true true false
$a = true false true false true true false false true
Table de vérité de $a == $b pour plusieurs valeurs

Avec ===, PHP va effectuer une comparaison stricte, et ne va faire aucune conversion, ce qui veut dire que le type de valeur est pris en compte. Le même tableau appliqué à === se présente ainsi :

$a == $b $b = '' $b = 1 $b = 0 $b = ' ' $b = 'a' $b = null $b = false $b = true
$a = '' true false false false false false false false
$a = 1 false true false false false false false false
$a = 0 false false true false false false false false
$a = ' ' false false false true false false false false
$a = 'a' false false false false true false false false
$a = null false false false false false true false false
$a = false false false false false false false true false
$a = true false false false false false false false true
Table de vérité de $a === $b pour plusieurs valeurs

Donc $a === $b vaut true uniquement si $a et $b sont exactement identiques (même valeur et même type

Cas particulier des objets

Les objets se comportent un peu différemment des types dits primitifs que sont les entiers, flottants, booléens et chaînes de caractères. Si on peut les comparer avec == comme avec ===, il est important de bien comprendre comment sont effectuées les comparaisons entre deux objets.

Deux objets comparés avec == sont égaux si :

  • ils sont de la même classe
  • ils ont les mêmes attributs
  • ces attributs ont les mêmes valeurs

Si vous avez des objets composés d’autres objets et que vous les comparez avec ==, la comparaison de ses attributs va se faire avec l’opérateur == aussi, et donc se passer comme pour les deux objets initiaux (comparaison de la classe, des attributs et valeurs de ceux-ci), et ce pour chaque propriété objet rencontrée parmi les enfants, petits-enfants, etc.. Notez donc que cela demandera des ressources.
En conséquence, si vous avez une relation circulaire entre vos deux objets comparés, cela va résulter en

PHP Fatal error: Nesting level too deep - recursive dependency? in…

En revanche, deux objets comparés avec === sont identiques s’ils sont la même instance de la même classe. Cela n’est donc possible que si l’on compare un objet avec lui-même. Deux objets ayant des attributs identiques et de valeurs identiques ne sont pas identiques, on l’a vu, c’est le cas de d’égalité mentionné ci-dessus.
C’est là la particularité des objets.

<?php
class Flag
{
    public $flag;

    function Flag($flag = true) {
            $this->flag = $flag;
    }
}

class OtherFlag
{
    public $flag;

    function OtherFlag($flag = true) {
            $this->flag = $flag;
    }
}
Deux classes pour l’exemple
$a = new Flag() $b = new OtherFlag() $b = new Flag() $b = clone $a $b = $a
$a == $b false true true true
$a === $b false false false true
Table de vérité pour la comparaison d’objets

Édité par Ymox

Evitez qu’on vous dise de les lire : FAQ PHP et SymfonyTutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+0 -0
Problèmes d’interprétation du PHP

Pourquoi est-ce que mon code n’est pas interprété et je le vois dans la page ?
Pourquoi est-ce que mon code PHP se télécharge plutôt qu’il ne s’éxécute ?
Pourquoi est-ce que mes echo n’affichent rien, mais je n’ai aucune erreur ?

L’URL a son importance

Si vous voyez au début de l’adresse

  • file://
  • C:\ (ou toute autre lettre majuscule suivie de :\)
  • un simple slash / ou antislash \

ET  qu'il n’y a pas http quand vous copiez-collez l’adresse, vous n’accédez pas correctement à vos fichiers.
Même les fichiers HTML de votre site ne doivent pas être ouverts avec le double-clic dès qu’il y a des pages PHP qui entrent en jeu

Le PHP ayant besoin d’être interprété par le serveur (ce qui n’est pas le cas du HTML), il faut qu’il soit quelque part où WAMP sait qu’il doit traiter du PHP, soit dans le dossier www de votre installation de WAMP. Vous devez y accéder avec une adresse commençant par http://, sans quoi vous ne passerez pas par WAMP.
Pour plus d’informations, lisez cette partie du tutoriel sur WAMP

Hé, j’y accède correctement, pourquoi ça ne fonctionne quand-même pas ?!

  1. Utilisez l’extension .php pour vos fichiers de code PHP, même si ceux-ci génèrent du HTML. Du code PHP dans un fichier avec l’extension .html peut soit s’afficher tel quel dans la page, soit ne pas être visible du tout

  2. Utilisez bien les marques ouvrantes PHP complètes <?php. Si vous souhaitez pouvoir utiliser les versions courtes <? (et <?= sous PHP < 5.4), il vous faut activer l’option short open tags pour PHP. Pour ce faire, cliquez sur l’icône de WAMP dans la zone de notifications, et allez sur PHP > Configuration PHP > short open tags (premier élément de la liste).

    Avant PHP 5.4, <?= était impacté par ce même paramètre

    Si vous avez des documents XML sur vos sites, surtout si vous les générez dynamiquement, activer cette option vous force à insérer la déclaration XML avec echo '<?xml version="1.0" encoding="utf-8" ?>'

  3. La balise <?php ne doit pas contenir d’espace. En revanche, elle doit absolument être suivie d’un caractère blanc (espace ou retour à la ligne). Par exemple :

    <?phpecho $truc; // ne fonctionnera pas, echo est "collé" à <?php
    <? php echo $truc; // ne fonctionnera pas, php n'est pas "collé" à <?
    

Édité par Ymox

Evitez qu’on vous dise de les lire : FAQ PHP et SymfonyTutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+0 -0

Comment récupérer l’id de l’enregistrement qui vient d’être inséré dans une table ?

Il faut utiliser la méthode de l’objet PDO lastInsertId()

<?php
$pdo = new PDO($dsn, $user, $passwd);
$pdo->exec("INSERT INTO ma_table (colonne1, colonne2) VALUES('$var_1', '$var_2')");
$id = $pdo->lastInsertId();
Exemple d’utilisation de PDO::lastInsertId

Selon la base de données et le driver utilisé, il est possible que le retour de cette fonction PDO soit totalement arbitraire

Avec l’API MySQLi, c’est la propriété mysqli#insert_id qui contient l’information.

$mysqli = new mysqli($host, $user, $password, $databaseName);
$mysqli->query("INSERT INTO ma_table (colonne1, colonne2) VALUES('$var_1', '$var_2')");
$id = $mysqli->insert_id;

// Ou, avec le style procédural
$mysqli = mysqli_connect($host, $user, $password, $databaseName);
mysqli_query($mysqli, "INSERT INTO ma_table (colonne1, colonne2) VALUES('$var_1', '$var_2')");
$id = mysqli_insert_id($mysqli);
Exemple d’utilisation de mysqli#insert_id

Édité par Ymox

Evitez qu’on vous dise de les lire : FAQ PHP et SymfonyTutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+0 -0

Comment connaître le nombre d’enregistrements affectés par une requête ?

C’est la méthode de l’objet PDOStatement rowCount() qui sert à cela

$pdo = new PDO($dsn, $user, $passwd);
$stmt = $pdo->prepare('UPDATE `message` SET `view` = `view` + 1 WHERE `sujet_id` = 37690510');
$stmt->execute();
$number = $stmt->rowCount();
Exemple d’utilisation de PDOStatement::rowCount

Vous pouvez l’utiliser pour des requêtes de type INSERT, UPDATE et DELETE

Avec MySQLi, il y a la propriété mysqli#affected_rows

$mysqli = new mysqli($host, $user, $password, $databaseName);
$mysqli->query('UPDATE `message` SET `view` = `view` + 1 WHERE `sujet_id` = 37690510');
$number = $mysqli->affected_rows;

// Ou, avec le style procédural
$mysqli = mysqli_connect($host, $user, $password, $databaseName);
mysqli_query($mysqli, 'UPDATE `message` SET `view` = `view` + 1 WHERE `sujet_id` = 37690510');
$number = mysqli_affected_rows($mysqli);
Exemple d’utilisation de mysqli#affected_rows

Vous pouvez l’utiliser pour des requêtes de type INSERT, UPDATE et DELETE. Pour les requêtes SELECT, c’est la propriété mysqli_result#num_rows qui doit être utilisée.

$mysqli = new mysqli($host, $user, $password, $databaseName);
$mysqli_result = $mysqli->query('SELECT * FROM `message` WHERE `sujet_id` = 37690510');
$number = $mysqli_result->num_rows;

// Ou, avec le style procédural
$mysqli = mysqli_connect($host, $user, $password, $databaseName);
$mysqli_result = mysqli_query($mysqli, 'SELECT * FROM `message` WHERE `sujet_id` = 37690510');
$number = mysqli_num_rows($mysqli_result);
Exemple d’utilisation de mysqli_result#num_rows

Dans certains cas avec des requêtes de type SELECT, l’information retournée peut être fausse

Dans ce cas, vous devez créer une requête avec la fonction SQL count() (ou l’équivalent pour votre SGBD) et récupérer la valeur comme n’importe quelle autre donnée.

Édité par Ymox

Evitez qu’on vous dise de les lire : FAQ PHP et SymfonyTutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+0 -0

J’ai modifié mon php.ini, mais ça ne change rien. Que se passe-t-il ?

Vous n’avez probablement pas redémarré Apache, ou pas modifié au bon endroit, ou sinon pas modifié le bon fichier^^
Il se peut que vous ayez plusieurs versions de PHP sur votre machine, ou que vous ayez modifié un fichier qui n’était pas pour "le bon environnement" (le bon SAPI1). Il y a cependant moyen de savoir quel fichier modifier rapidement.

Pour votre serveur HTTP (accès par navigateur)

Si vous utilisez WAMP, c’est le fichier qu’il vous est proposé de modifier en passant par le menu de l’icône (voir le dernier bloc « Attention »).

Regardez dans le phpinfo (vous pouvez vous créer une page ne contenant que <?php phpinfo() si besoin) aux lignes suivantes :

  • Loaded Configuration File
    Si vous êtes en local et que changer la configuration pour toutes vos applications PHP ne vous pose pas de problème, c’est le  fichier à modifier

    N’oubliez pas de redémarrer Apache après cette modification.

  • Scan this dir for additional .ini files
    Si vous êtes chez votre hébergeur et que la valeur de cette ligne est bien un chemin, il peut être intéressant de voir si vous pouvez vous rendre dans le dossier qui est mentionné (il y aura probablement des parties à remplacer par votre nom d’utilisateur ou un identifiant quelconque), afin d’y créer votre fichier php.ini. Ce fichier peut devoir être nommé d’une certaine manière, surtout au niveau de l’extension.
    Pour savoir cela, regardez plus bas dans les phpinfo pour trouver la ligne user_ini.filename. Par défaut, les fichiers php.ini par utilisateur sont à nommer avec la double extension .user.ini.

    Tout n’est pas paramétrable avec de tels fichiers. Conformez-vous à la colonne « Modifiable » de la page listant les directives du php.ini

  • Additional .ini files parsed
    Ça, c’est justement pour voir s’il n’y a pas déjà un php.ini existant et qui vous serait propre. Dans le cas où il y a un fichier d’indiqué et que vous pouvez y accéder, c’est là que vous pourrez faire vos modifications. Si vous ne pouvez pas y accéder, il y a de fortes chances que votre hébergeur puisse et soit d’accord de le faire pour vous. Soyez néanmoins convaincants  ;)

Au final, si votre hébergement fonctionne avec Apache, vous avez aussi la possibilité de définir des valeurs de PHP dans des fichiers .htaccess.

Pour la ligne de commandes

Hé oui, il y a parfois (et même souvent) plusieurs php.ini, un par SAPI. En général, ils ne sont pas nommés de la même manière ou ne sont pas enregistrés au même endroit.

Là, c’est très simple, il suffit de taper une commande qui va directement donner le chemin complet du fichier à modifier : la commande php --ini.
En revanche, il est extrêmement rare que les hébergeurs laissent modifier celui-ci.


  1. Plus d’informations à ce sujet sur Wikipédia

Édité par Ymox

Evitez qu’on vous dise de les lire : FAQ PHP et SymfonyTutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+1 -0
Jeux de caractères et encodage (2)

Pourquoi est-ce que les fonctions sur mes chaînes de caractères ne me retournent rien ?
Pourquoi est-ce que tous les caractères de mes chaînes ne sont pas mis en majuscules/minuscules ?

Concerne aussi le point 3 de cette entrée

Aussi surprenant que cela puisse paraître, c’est un souci de jeux de caractères et donc de caractères spéciaux.
Le jeu de caractères interne de PHP et celui de votre chaîne à traiter ne sont pas cohérents : vous envoyez de l’ISO 8858–1(5) (qui est le jeu de caractères par défaut avec PDO) alors que ces fonctions attendent de l’UTF-8. Ne pouvant traiter la chaîne correctement, elles retournent NULL.

Ceci concerne les fonctions htmlentities(), html_entity_decode(), htmlspecialchars(), json_encode(), json_decode(), et la plupart des fonctions str*(), qui sont prévues pour retourner des chaînes de caractères dans un jeu précis, et n’acceptent que ce jeu précis comme entrée. Ainsi, alors que PHP avant 5.4 utilisait ISO 8859–1, dès PHP 5.4, on est en UTF-8.

Les versions de PHP avant 5.4 pouvaient aussi retourner des chaînes pas totalement traitées ou tronquées quand le jeu de caractères fourni n’était pas de l’UTF-8.

Solution pour htmlentities(), html_entity_decode(), htmlspecialchars() : spécifiez les deuxième et troisième paramètres

Pour ces trois fonctions, dès PHP 5.6, c’est le jeu de caractères spécifié pour default_charset dans le php.ini (voir le point 5 de ce message) qui est utilisé par défaut

Solution pour les fonctions str*() AVANT PHP 7.2 : utilisez leurs équivalents mb_str*() ou activez mbstring.func_overload pour le "groupe 2"

Solution pour les fonctions json_*() : là, il n’y a malheureusement pas d’autre alternative que de leur fournir de l’UTF-8.

En complément, regardez ce message pour d’autres éléments à vérifier en relation avec les jeux de caractères.

Édité par Ymox

Evitez qu’on vous dise de les lire : FAQ PHP et SymfonyTutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+0 -0

Comment vérifier si un pseudo ou une adresse mail (ou toute autre valeur) est déjà utilisée ? Je n'aimerais pas de doublons.

Il y a au moins deux possibilités pour gérer cela.

Vérifier le nombre d'occurrences existantes

L'idée est de faire une requête qui va compter dans la base de données le nombre d'occurrences de la valeur. Le test ressemblera à ceci :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?php
$declarationRequete = $pdo->prepare(
    'SELECT count(`id`) FROM `une_table` WHERE `la_colonne` = :la_valeur'
);
$declarationRequete->execute(array('la_valeur' => $laValeur));

if ($declarationRequete->fetchColumn() > 0) {
    // On a un ou plusieurs résultats, la valeur ne peut être enregistrée
} else {
    // On n'a aucun résultat, on va pouvoir faire INSERT
}

Vérification si une valeur n'est pas déjà dans la BDD (à répéter autant de fois que de valeurs)

Notez que si vous avez plus d'un résultat ($declarationRequete->fetchColumn() retourne un nombre plus élevé que 1), vous avez un problème.  :-°

Cette méthode vous permet, en cas de plusieurs valeurs qui doivent être uniques, de savoir exactement lesquelles le le sont pas.
En revanche, elle demande une requête supplémentaire par valeur à garder unique.

Ajouter des index d'unicité sur la ou les colonnes contenant les valeurs qui doivent être uniques

L'idée est que ce ne soit plus vous qui vérifiez l'unicité dans votre programme, mais votre moteur SQL. Ainsi, à l'insertion des données, vous vérifiez si celle-ci s'est bien passée, soit en capturant l'exception levée1, soit en testant le retour de l'exécution de la requête.

La requête pour ajouter une contrainte d'unicité ressemble à ceci :

1
CREATE UNIQUE INDEX unique_ma_valeur ON `une_table` (`la_colonne`)

Création d'une contrainte d'unicité sur une colonne avec MySQL (à répéter autant de fois que de valeurs à conserver uniques)

La partie PHP, elle, ne change que très peu :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?php
$declarationRequete = $pdo->prepare('INSERT INTO `personne` VALUES (NULL, :pseudo, :email)');
$declarationRequete->bindParam('pseudo', $_POST['pseudo']);
$declarationRequete->bindParam('email', $_POST['email']);

// PDO en mode silencieux
if ($declarationRequete->execute()) {
    /* L'insertion s'est effectuée sans problème */
} else {
   /* Il y a eu un problème à l'insertion */
}

// PDO en "mode d'erreur exceptions"
try {
    $declarationRequete->execute();
    /* Le code à partir de cette ligne et avant la 18 ne sera 
     * effectué que si la requête n'a pas généré d'erreur */
} catch(\Exception $e) {
    /* Il y a eu un problème à l'insertion */
}

Deux manières de vérifier l'insertion avec des contraintes d'unicité

Vous ne pourrez pas savoir de manière aisée quelle valeur a posé problème, donc cette méthode est plus adaptée à une seule valeur à vérifier.
Cependant, vous n'avez dans tous les cas qu'une seule requête.


  1. Notez que ceci devrait être fait, car la requête peut toujours générer une exception.
    Notez encore qu'il faut avoir demandé à l'API de connexion de notifier des erreurs SQL. 

Édité par Ymox

Evitez qu’on vous dise de les lire : FAQ PHP et SymfonyTutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+0 -0

Mon code fonctionne en local, mais pas sur le serveur final, pourquoi ?

Il peut y avoir beaucoup de paramètres à la base de ce problème, mais tous ont un dénominateur commun : la version et les paramètres de PHP.

Comparez un phpinfo() en local et sur le serveur pour voir les différences. Si certaines ne porteront pas nécessairement à conséquence pour votre code, une simple différence de version mineure (le second chiffre) peut poser problème, sans parler des autres paramètres.

Il arrive aussi que la casse pose problème à différents niveaux, que ce soit au niveau du nom des fichiers ou des tables/colonnes de la base de données.

Dans bien des cas, l’activation des messages d’erreur sur le serveur distant reste un bon moyen de savoir ce qu’il se passe et d’avoir des pistes.

Édité par Ymox

Evitez qu’on vous dise de les lire : FAQ PHP et SymfonyTutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+0 -0

Comment remplacer des antislashs ou backslash (\\) par des slashs (/) avec preg_replace().

Dans un premier temps, vous seriez tentés de l'écrire de cette façon :

1
2
3
4
<?php
$string = 'D:\\wamp\\www\\';
$foo    = preg_replace('/\\/', '/', $string); // A ne pas faire
echo $foo;

Sauf que vous aurez le droit à une erreur du type : Message: preg_replace(): No ending delimiter '/' found.

Il faut, comme indiqué dans la documentation officielle, doubler les antislashs.

1
2
3
4
<?php
$string = 'D:\\wamp\\www\\';
$foo    = preg_replace('/\\\\/', '/', $string);
echo $foo;  # D:/wamp/www/
Edit Ymox

Echappement des antislashes dans la déclaration de $string

Edit viki53

Fix typo

Édité par elyppire

HTTP/1.1 418 I’m a teapot

+0 -0

Comment désactiver le header X-Powered-By généré par défaut sur PHP ?

Allez dans le fichier de configuration de PHP php.ini et remplacez la ligne expose_php = On par expose_php = Off.

Édité par elyppire

HTTP/1.1 418 I’m a teapot

+0 -0

Comment faire pour que mon script puisse être utilisé n’importe où, que ce soit à la racine d’un hébergement ou dans un sous-dossier ?

Vous pouvez utiliser la fonction path() avec le code ci-dessous sur vos liens. Elle ajoutera la partie qui peut varier d’un environnement à l’autre au besoin.

Codez tout comme si vous travailliez à la racine d’un nom de domaine. Vous pouvez ensuite utiliser la fonction path() sur tous vos liens absolus dans votre code PHP/HTML.

<?php
// On récupère les dossiers dans l'URI de la requête
$uri = preg_split('`/|\\\`', $_SERVER['REQUEST_URI'], -1, PREG_SPLIT_NO_EMPTY);

// On regarde ce qu'elle a en commun d'avec le chemin du script
$baseUrl = array_intersect(
    $uri,
    preg_split(
        '`/|\\\`',
        realpath(dirname(__FILE__)),
        -1,
        PREG_SPLIT_NO_EMPTY
    )
);
if (count($baseUrl)) {
    // S'il y a des trucs en commun, on se construit une base d'URL
    define('BASE_URL', '/' . implode('/', $baseUrl));
} else {
    // Sinon, c'est qu'on est à la racine de l'hébergement
    define('BASE_URL', '');
}

/**
 * Permet de rendre des liens absolus portables
 * @param string $link Le lien à traiter
 */
function path($link)
{
    // Si on a un URL absolu…
    if (preg_match('`^/`', $link)) {
        // … on ajoute BASE_URL devant.
        $link = BASE_URL . $link;
    }
    // On retourne le lien
    return $link;
}
De quoi permettre de rendre des codes PHP portables

Par sécurité, les liens relatifs ne devraient pas poser de problème si traités avec cette fonction, donc vous pourriez traiter tous vos liens sans réfléchir, ce que nous ne vous conseillons cependant pas.  :p

Édité par Ymox

Evitez qu’on vous dise de les lire : FAQ PHP et SymfonyTutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte