GET/POST /quote_feedback_comments/delete/id:{comment_id}.json

狀態:PHP 8 本地實作與測試完成,Staging 尚未驗證。
最後更新:2026-07-31

快速結論

  • id 是 CakePHP colon named parameter,經 (int) cast。
  • 只允許 comment_user_id = session user id 的本人 hard delete。
  • 不查 feedback,因此孤兒 comment 仍可由 owner刪除。
  • Legacy 沒有限制 HTTP method;Production 同時有 POST 與 GET,不可自行改成只接受 DELETE/POST。
  • 成功固定回 {"error":0,"message":"success"}

Route、caller 與流量

正式流量形態:

POST /quote_feedback_comments/delete/id:{comment_id}.json
GET  /quote_feedback_comments/delete/id:{comment_id}.json
  • Production 2026-06-29~2026-07-28:POST 7、GET 3,全部命中 Legacy。
  • 現行 web-app 找不到 delete caller;仍有正式流量,可能來自舊 App/其他 client,不能刪除 GET 支援。
  • 2026-07-31 掃描 Legacy host ip-10-5-2-19 全部保留的 get-lancer_access.log*:命中 3 筆 delete path,全部以 .json 結尾;其他 instances/ALB 尚待確認。

PHP 8 已使用明確且 anchored mapping:

^quote_feedback_comments/delete/id:([0-9]+)\.json$
→ QuoteFeedbackComments::delete / id / ${1}

專用 mapping 與 generic File fallback 都有測試,涵蓋 invalid named value、slash/query path與 unknown action。

程式位置

Legacy

Root:/Users/mattsu/Documents/Site/get-lancer-docker-2/get-lancer

  • app/Plugin/Quotes/Controller/QuoteFeedbackCommentsController.php
    • beforeFilter():8-18。
    • delete():106-142。
    • session/request log:109-113。
    • named input/owner query:118-127。
    • hard delete/success:130-135。
    • error mapping:137-140。
  • app/Plugin/Quotes/Model/QuoteFeedbackComment.php:2-18:只有 belongsTo User,無 delete callback/dependent association。
  • app/Controller/RestApiHelper.php:75-182:session、auth side effect、request info log。
  • app/Controller/AppController.php:1223-1226, 1313-1343:named input、JSON response與 error warning log。

PHP 8

  • Endpoint/V1/QuoteFeedbackComments.php
    • delete():94-130。
    • .json 副檔名 guard:132-135。
    • Legacy session/cache/access side effect:137-249。
    • auth/action error response:222-265。
    • request log:266-290、312-333。
    • 原始 colon named parser:345-364。
  • Lib/Model/QuoteFeedbackComment.php
    • owner lookup:26-34。
    • hard delete:77-81。
  • Lib/Common/RouterRule/Mapping.php:160-163:anchored delete mapping。
  • tests/QuoteFeedbackCommentsSaveDeleteTest.php:384-559:GET/POST、owner、orphan、cast與 route negative。

逐段對照

階段LegacyPHP 8 現況/要求
guardLegacy 可由 .jsonAccept 判定 JSON;另驗 API key、sessionPHP 8 只接受 .json;其餘 auth 已對齊
inputcolon named id,PHP 5.6 (int)已從 original path 解析,slash/query 不誤收
DB readcomment id+session user id已對齊
DB writehard delete一筆 comment已對齊;不 join feedback
payment不適用不可新增
queueendpoint無;auth cache miss可能 returnedQuoteService已保留 Legacy auth 時機
activity不適用不可新增
notification不適用不可新增
logrequest info;error warningLegacy log 已保留;generic 差異待決策
responsesuccess與 code 1/3/4/999已對齊並測試型別

Migration decision(2026-07-31,reviewer 已接受):PHP 8 不搬 Legacy RequestHandler->prefers('json') 的 Accept negotiation,只接受 .json URL。ip-10-5-2-19 retained logs 只看到 .json;無副檔名即使帶 Accept: application/json 也先回 {"error":1,"status":"invalid request"},不執行 delete。

執行順序與 input

  1. Request URL 必須以 .json 結尾,且通過 API key/session。
  2. 取得 session user並寫 Legacy endpoint request info log。
  3. 讀 colon named id,PHP 5.6 (int) cast。
  4. id=0 時回 code 3;其他值查 id + comment_user_id
  5. 查無資料時回 code 4;查到即 hard delete。
URL inputLegacy 行為
missing、id:0id:abcid:cast 0error=3
id:1abccast 1,查 comment 1
id:-1cast -1,查無則 error=4
id:{owner row}hard delete並 success
id:{other user row}查詢即排除,error=4
slash /id/1 或 query ?id=1不是 Cake named parameter;PHP 8 已驗證為 error=3 且不刪除,Legacy實測待補

DB write

SELECT id
FROM quote_feedback_comments
WHERE id=:comment_id
  AND comment_user_id=:session_user_id
LIMIT 1;
 
DELETE FROM quote_feedback_comments
WHERE id=:comment_id;
  • 只刪一筆 comment;沒有 soft-delete欄位、transaction、cascade、feedback update、counter、activity、notification或 queue。
  • 不可額外 join quote_feedbacks 或要求 feedback存在。Docker DB目前有 201 筆找不到 feedback的 orphan comments。
  • 必須驗證 affected row 與測試 fixture restore;Legacy controller不檢查 delete()回傳值,找到 row後即回 success。

Response 與 error

成功:HTTP 200、application/json; charset=utf-8

{"error":0,"message":"success"}

action 內錯誤:

情境Body
invalid request/session path{"error":1,"status":"invalid request"}
missing/0 id{"error":3,"status":"require_comment_id"}
不存在或非 owner{"error":4,"status":"CommentNotFound"}
unknown exception{"error":999,"status":"invalid request"}

Invalid API key由全域 guard回 HTTP 401;blocked user為 HTTP 403。Invalid session可能先被 Legacy ACL 攔截,最終 HTTP/body仍需 Legacy Staging實測確認。

Side effect、log 與 config

  • Domain side effect只有 hard delete。
  • auth cache hit/miss、blocked check、user access與 returned-service queue時機必須與 Legacy相同,不可直接用 PHP 8 shared validator。
  • request info log channel保留完整 path與實際 method ::GET::POST;message為 user id,context含原始 API key,若有 request data/form也照記。
  • error另由 handleProApiException()QuoteFeedbackCommentsController warning。
  • PHP 8 已保留 Legacy endpoint request log與 error warning,並停用這些相容 log 的 PHP 8 Slack handler。
  • Router generic log與 client_usage_users 是 Legacy沒有的額外行為,migration decision待 reviewer確認。
  • 無 endpoint專用 ProConfig、URL、template、payment設定;部署只需核對 DB、Redis與 session共享狀態。

PHP 5.6 → 8.2 必測

  • colon named parsing及 (int):missing、0abc1abc、negative。
  • GET/POST都能執行;不得加 method guard。
  • owner查詢型別與不存在/非 owner同樣回 code 4。
  • hard delete成功與 DB failure時Legacy未檢查結果的行為。
  • slash/query、duplicate named、URL-encoded named及 unknown action route negative。

測試與待辦

  • PHP 8.2 syntax:通過。
  • 全域 core3 tests / 36 assertions;delete 核心覆蓋 GET/POST owner hard delete,並確認 non-owner 不可刪除。
  • Other(--exclude-group core):16 tests / 97 assertions;保留 orphan、missing/0/invalid/negative/prefix cast、slash/query negative、response value/type與 route guard。專用測試合計 19 / 133
  • Regression:quote_feedbacks/sent 10/76、quote_feedback_tags/index 12/68,全部通過。
  • 尚待:其他 Production instances/ALB 的非 .json 流量、Legacy/Staging response baseline、Staging hard-delete後 restore、未知 client確認、部署 Redis 核對、generic log/client_usage_users 決策。Production ALB 不在本文件修改。