web-dev-qa-db-fra.com

Vérifier si la requête INSERT a réussi ou échoué en raison d'un doublon UNIQUE KEY

J'ai une table de base de données appelée league où la colonne mail est l'identifiant unique:

|name |mail               |
|Bryan|[email protected]  |

J'ai un frontend où les utilisateurs peuvent s'inscrire et ensuite j'ai ceci pour le backend:

$db = JFactory::getDbo();
$query = $db->getQuery(true);
$jinput = JFactory::getApplication()->input;

$name = $jinput->getString('name');
$mail = $jinput->getString('mail');

$columns = array('name', 'mail');

$values = array($db->quote($name), $db->quote($mail));

$query
    ->insert($db->quoteName('league'))
    ->columns($db->quoteName($columns))
    ->values(implode(',', $values));

$db->setQuery($query);
$db->execute();

Maintenant, si Bryan essaie de s'inscrire avec le même courrier, une erreur se produit. Comment puis-je écrire un message au lieu de la page d'erreur normale? Je veux quelque chose comme: "Merci pour votre inscription" si la requête aboutit et "vous êtes déjà inscrit" si la requête échoue.

3
Daniel Jensen

Vous devrez effectuer une requête select sur votre table de base de données, en recherchant l'adresse électronique. Si un résultat est renvoyé, vous pouvez envoyer un message d'alerte, sinon exécutez la requête insert, comme ceci:

$jinput = JFactory::getApplication()->input;
$name   = $jinput->getString('name');
$mail   = $jinput->getString('mail');

$db = JFactory::getDbo();

$query = $db->getQuery(true)
      ->select($db->quoteName('mail'))
      ->from($db->quoteName('league'))
      ->where($db->quoteName('mail') . ' = '. $db->quote($mail));
$db->setQuery($query);

$result = $db->loadResult();

if (!$result)
{
    $columns = array('name', 'mail');
    $values = array($db->quote($name), $db->quote($mail));

    $query = $db->getQuery(true);

    $query->clear();
    $query->insert($db->quoteName('league'))
        ->columns($db->quoteName($columns))
        ->values(implode(',', $values));

    $db->setQuery($query);
    $db->execute();
}
else
{
    JFactory::getApplication()->enqueueMessage('Email already exists', 'error');
}
3
Lodder

Étant donné que mail est une clé de table UNIQUE (PRIMARY fonctionne de la même manière), vous pouvez accomplir la logique que vous visez avec une seule requête. Conformément aux meilleures pratiques de codage, vous devez toujours effectuer le moins de requêtes possible.

Comme vous le verrez, il n’ya aucune raison d’appeler une requête SELECT. Si aucune erreur/exception n'est détectée, votre INSERT a réussi. Si une adresse électronique en double est soumise, une exception très informative sera générée. Il vous suffit d'écouter le code d'erreur potentiel: 1062.

Code:

$jinput = JFactory::getApplication()->input;
$name = $jinput->getString('name');
$mail = $jinput->getString('mail');

if (!filter_var($mail, FILTER_VALIDATE_EMAIL)) {
    JFactory::getApplication()->enqueueMessage('Invalid Email. Please Check Email & Try Again.', 'notice');
} else {
    $db = JFactory::getDBO();
    try {
        $query = $db->getQuery(true)
                    ->insert($db->qn('league'))
                    ->columns($db->qn(array('name', 'mail')))
                    ->values($db->q($name) . ',' . $db->q($mail));
        $db->setQuery($query);
        $db->execute();
        JFactory::getApplication()->enqueueMessage('Success!', 'message'); // is only reached if no errors
    } catch (Exception $e) {
        if ($e->getCode() == 1062) {
            JFactory::getApplication()->enqueueMessage('Duplicate Email. Please Try Another Email.', 'notice');
        } else {
            JFactory::getApplication()->enqueueMessage('Syntax Error. Please Contact Developer.', 'error');
        }
    }
}

Quelques autres petites notes:

  • J'ai créé une étape de validation pour l'entrée mail en tant que suggestion auxiliaire.
  • Parce que vos tableaux $columns Et $values Sont "à usage unique", j'ai décidé de ne pas les déclarer et j'ai simplement ajouté les données directement dans les méthodes de requête respectives.
  • J'utilise q() comme raccourci pour quote() et qn() pour quoteName() par souci de brièveté. Pour mémoire, votre requête sera tout aussi sûre/couronnée de succès sans aucun des appels qn(), car vous utilisez des mots statiques uniques et aucun mot n'est réservé à la MYSQL RESERVED.
  • Pour illustrer la règle que j'utilise, consultez ceci Démo SQLFiddle qui tente d'insérer deux lignes avec la même valeur de courrier électronique. Il ne montre pas le code d'erreur, juste le message d'erreur.
2
mickmackusa