案例:quote_requests copy

/quote_requests/copy.json 使用「hash 優先,session fallback」。

程式位置

專案位置
舊專案入口get-lancer-php56/app/Plugin/Quotes/Controller/QuoteRequestsController.php::copy()
新專案入口pro360_api_82/Endpoint/V1/QuoteRequests.php::copy()
新專案 handlerpro360_api_82/Lib/QuoteRequestCopy/CopyRequestHandler.php::handle()

資料表關聯

資料表用途關聯
quote_requests要被複製的 requestquote_requests.id = sourceRequestId
security_hasheshash 驗證model='QuoteRequest', foreign_id=quote_requests.id
api_sessionsfallback session 驗證session token -> user
users最終 user identityhash 或 session 都會解析到 user id

驗證規則

順序規則成功時 user id
1若有 hash,查 security_hashes尚未通過
2model 必須是 QuoteRequest尚未通過
3foreign_id 必須等於 source request idsecurity_hashes.user_id
4hash 不通過時,檢查 session$usersDO->id
5hash/session 都不通過invalid session

新專案核心程式

if ($hash !== '') {
    $hashRecord = (new SecurityHash())->getByHash('QuoteRequest', $hash);
    if (is_array($hashRecord) && (int)($hashRecord['foreign_id'] ?? 0) === $sourceRequestId) {
        $passed = true;
        $resolvedUserId = (int)($hashRecord['user_id'] ?? 0);
    }
}
 
if (!$passed) {
    $usersDO = null;
    $passed = ApiValidation::hasValidApiSession($request, true, $usersDO);
    if ($passed && $usersDO !== null) {
        $resolvedUserId = (int)$usersDO->id;
    }
}

容易誤判

  • hash 字串存在不代表通過,還要比 foreign_id
  • hash 失敗不一定失敗,這支 API 會 fallback session。