0

API の独自の実装を作成しています。この API のリソースの 1 つは です。これに文字列を渡し、解析して、メソッドを持つに送信/userできます。明らかに、2 人のユーザーが同じユーザー名を持つことを許可することはできません。これは私がこれまでのところしなければならないことです。POSTJSONUserServiceaddUser

protected function handlePost() {
    $user = json_decode($this->getRequest()->getRequestData(), true);

    try {
        $createdUserId = $this->userService->addUser(
            $user['username'],
            $user['password'],
            $user['typeId'],
            $user['companyId']
        );
    } catch (PDOException $e) {
        $this->getResponse()->setStatus(102);
    }

    if ($createdUserId)
        $this->getResponse()->setStatus(101);

    $this->getResponse()->sendResponse();
}

この関数は、HTTP 要求が解析された後に呼び出されます。ご覧のとおり$user、連想配列でオブジェクトを取得します。次に、これらの値を$this->userService->addUserメソッドのパラメーターとして使用します。

これはaddUser()方法です:

public function addUser($username, $password, $type, $companyId) {
    $sth = $this->dbh->prepare('INSERT INTO app_user
                                (username, password, typeId, companyId)
                                VALUES (?, ?, ?, ?)');
    $userAdded = $sth->execute(array($username, md5($password), $type, $companyId));

    return ($userAdded)
        ? $this->dbh->lastInsertId()
        : null;
}

$sth->execute何らかの理由で失敗した場合は、 null を返します (ステータス コード 101 も 102 も返されません。これは承知しています)。しかし、ユーザー名が既に存在する場合、PDO は例外をスローします。これをhandlePost()上記のメソッドでキャッチします。

もちろん、これに関する私の問題は、すでに使用されているユーザー名が例外的ではなく、このように処理されるべきではないということですが、どのように処理すればよいか本当にわかりませんか?

トリガーされている一意の制約と、トリガーされているその他の制約 (おそらく同時実行の問題) を区別できるようにして、適切なステータス コードを API のコンシューマーに送り返すことができるようにする必要があります。

明らかな解決策は、ユーザー名が別のクエリに存在するかどうかを確認することですが、明らかな理由から、データベースへの呼び出しを制限したままにすることをお勧めします。

これをエレガントに解決するにはどうすればよいですか?例外を使用する必要がある場合、ジェネリックを使用する必要がないように、特定の PDO 例外のリストはありPDOExceptionますか?

4

2 に答える 2

1

挿入を試みる前にデータベース内のユーザー名の存在をチェックするだけでなく、パフォーマンス (つまり、データベースに対するクエリを最小限に抑えること) に十分に関心がありますか? 例外をキャッチして、最後のクエリなどで影響を受けた行の数に基づいて、本当に例外があるかどうかを判断するよりも、この簡単なロジックに従うことができます。

また、例外にならないようにしたい場合は、挿入に ON DUPLICATE KEY ロジックを追加することもできます。

于 2012-07-23T19:05:09.353 に答える
1

PDO コンストラクターで ERRMODE_EXCEPTION を使用していない場合、PDO は整合性制約違反の例外を送信するべきではありません。

その場合、メソッド PDOStatement::errorCode() または PDOStatement::errorInfo() を呼び出す必要があります。

エラーの詳細を取得し、それが整合性制約違反なのか実際の問題なのかを確認します。

于 2012-07-23T19:05:38.793 に答える