HTTPリクエストからJSONオブジェクトを取得する際、事前にヌルチェックを行わないとセグメンテーションフォールトが発生する可能性があります。
if (!req->getJsonObject()) {
throw std::invalid_argument("リクエストボディに有効なJSONが含まれていません");
}
auto jsonInput = req->getJsonObject();
DrogonのORM Mapperクラスは、SQL制約(limit, offsetなど)をメソッドチェーン形式でサポートしています。これらの制約は1回のクエリ実行後にクリアされるため、毎回明示的に設定する必要があります。
Mapper<User> userMapper(dbClient);
auto users = userMapper
.orderBy(User::Cols::_created_at)
.limit(25)
.offset(0)
.findAll();
上記コードは、ユーザーを登録日時でソートし、1ページ目(25件)を取得します。offsetは手動で計算する必要がある点に注意してください。
以下は、安全なページネーション処理の実装例です:
Json::Value response;
response["status"] = "success";
try {
auto jsonBody = req->getJsonObject();
if (!jsonBody) {
throw std::runtime_error("JSONパラメータが必須です");
}
int currentPage = (*jsonBody).get("page", 1).asInt();
int itemsPerPage = (*jsonBody).get("pageSize", 10).asInt();
if (currentPage < 1 || itemsPerPage < 1) {
throw std::invalid_argument("pageおよびpageSizeは正の整数である必要があります");
}
int skipItems = (currentPage - 1) * itemsPerPage;
auto db = drogon::app().getDbClient();
Mapper<Administrator> adminMapper(db);
auto admins = adminMapper
.orderBy(Administrator::Cols::_id)
.limit(itemsPerPage)
.offset(skipItems)
.findAll();
Json::Value result;
result["total"] = static_cast<int>(admins.size());
Json::Value adminArray;
for (const auto& admin : admins) {
adminArray.append(admin.toJson());
}
result["items"] = adminArray;
response["payload"] = result;
auto httpResponse = HttpResponse::newHttpJsonResponse(response);
callback(httpResponse);
} catch (const std::exception& ex) {
response["status"] = "error";
response["message"] = ex.what();
auto errorResp = HttpResponse::newHttpJsonResponse(response);
errorResp->setStatusCode(k400BadRequest);
callback(errorResp);
}
Mapperのチェーンメソッドは直感的な命名となっており、詳細はソースコード内のMapper.hを参照してください。