0

我正在编写自己的 API 实现。这个 API 的资源之一是/user,我可以给它POST一个JSON字符串,解析它并将它发送给一个UserServiceaddUser方法的。现在显然我不能允许两个用户拥有相同的用户名。这是我到目前为止所要做的。

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 回答