Charlie PHP Expert - Volume 11D | 1 CHARLIE PHP EXPERT Volume 11D - Final Fix Strict Browser Fetch / HTTP / JSON Separation Purpose: Eliminate the final two regressions found after Volume 11C: (1) using typeof data !== 'object' to detect malformed JSON, and (2) wrapping more than fetch() inside the network try/catch. Override rule: For browser-side JavaScript Fetch/HTTP/JSON handling, this final correction supersedes any older example that conflicts with it. 1. Final Rule: Never Use typeof to Detect Malformed JSON Malformed JSON is detected when await response.json() throws. Do not test parsed data with typeof data !== 'object'. Valid JSON can represent an object, array, string, number, boolean, or null. 2. Final Rule: Scope the Network catch to fetch() Only The network/transport try/catch must contain only the operation that obtains the HTTP Response: await fetch(). Do not include HTTP status handling, JSON parsing, business logic, or later processing inside that same catch. Otherwise unrelated errors may be mislabeled as network failures. 3. Canonical Final Implementation async function requestJson(url, options = {}) { let response; // A. NETWORK / TRANSPORT try { response = await fetch(url, options); } catch (error) { return { ok: false, kind: "network", message: "No HTTP response was obtained.", cause: error }; } // B. HTTP STATUS if (!response.ok) { let errorBody = null; try { errorBody = await response.json(); } catch (_) { try { errorBody = await response.text(); } catch (_) { errorBody = null; } } return { ok: false, kind: "http", status: response.status, statusText: response.statusText, body: errorBody }; } // C. JSON PARSING Charlie PHP Expert - Volume 11D | 2 try { const data = await response.json(); return { ok: true, kind: "success", status: response.status, data }; } catch (error) { return { ok: false, kind: "json", status: response.status, message: "Response body was not valid JSON.", cause: error }; } } 4. Four Canonical Outcomes Scenario Classification fetch() throws before Response exists network HTTP 500 with valid JSON error body http HTTP 200 with malformed JSON body json HTTP 200 with valid JSON body success 5. PHP Server-Side Trust Boundary Browser validation is advisory only. PHP must independently enforce required fields, types, ranges, formats, business rules, authentication, authorization, tenant scope, duplicate protection where relevant, and data-integrity constraints. Use parameterized database operations and context-appropriate output encoding/sanitization rather than treating generic 'sanitization' as a substitute for validation or authorization. 6. API Contract Mismatch If JavaScript expects {success: true, data: ...} but PHP returns {status: 'ok', result: ...}, identify the mismatch, choose one authoritative schema, update the client and/or server to that schema, document it, and add tests so the mismatch cannot silently return. 7. Forbidden Regression Patterns Do not use typeof data !== 'object' as malformed-JSON detection. Do not classify by TypeError, error name, or error message when the failing operation already identifies the boundary. Do not place fetch(), HTTP classification, and response.json() in one generic catch. Do not mix PHP syntax into JavaScript. 8. Final Certification Prompt Prompt: A browser sends form data to a PHP API using fetch(). Handle these separately with valid JavaScript and async/await: (1) fetch fails before any Response exists, (2) PHP returns HTTP 500 with valid JSON, (3) PHP returns HTTP 200 with malformed JSON, (4) PHP returns HTTP 200 with valid JSON. Do not classify using error type/name/message and do not use typeof to test whether JSON is malformed. Then explain server-side validation and an API contract mismatch. Pass requirement: 90/100 or higher with no critical regression. The network catch must scope only the fetch operation; HTTP status must be evaluated after a Response exists; malformed JSON must be detected only by the parsing operation failing.