web-dev-qa-db-ja.com

重複する一意キーが原因でINSERTクエリが成功したか失敗したかを確認します

leagueというdbテーブルがあり、mail列は一意のIDです。

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

ユーザーがサインアップできるフロントエンドがあり、バックエンド用にこれがあります:

$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();

これで、Bryanが同じメールでサインアップしようとすると、エラーが発生します。通常のエラーページの代わりにメッセージを書き込むにはどうすればよいですか?クエリが成功した場合は「サインアップしていただきありがとうございます」、クエリが失敗した場合は「すでにサインアップしています」のようなものが必要です。

3
Daniel Jensen

電子メールアドレスを検索して、データベーステーブルに対してselectクエリを実行する必要があります。結果が返された場合は、警告メッセージをスローできます。それ以外の場合は、次のようなinsertクエリを実行します。

$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

mailはUNIQUEテーブルキーであるため(PRIMARYも同じように機能します)、1つのクエリだけで目的のロジックを実現できます。コーディングのベストプラクティスに従って、できるだけ少ないクエリを常に実行する必要があります。

ご覧のとおり、SELECTクエリを呼び出す理由はありません。キャッチされたエラー/例外がない場合、INSERTは成功しています。重複したメールアドレスが送信された場合、非常に有益な例外が生成されます。潜在的なエラーコードをリスンするだけで済みます:_1062_。

コード:

_$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');
        }
    }
}
_

他のいくつかの小さなメモ:

  • 補助的な提案として、mail入力の検証手順を実行しました。
  • _$columns_および_$values_配列は「使い捨て」であるため、それらを宣言せず、それぞれのクエリメソッドにデータを直接追加することにしました。
  • 私はq()の短縮形としてquote()を使用し、簡潔にするためにqn()quoteName()を使用しています。レコードの場合、単一の静的な単語を使用していて、MYSQL RESERVEDの単語はないため、qn()の呼び出しがなくても、クエリは同じように安全/成功します。
  • 私が活用しているルールを示すには、これを参照してください SQLFiddle Demo は、同じ電子メール値を持つ2つの行を挿入しようとします。エラーコードは表示されず、エラーメッセージのみが表示されます。
2
mickmackusa