first php projects
JSON API
Expose part of the product catalog as JSON. Reuse the repository rather than building a second data-access path. The API is a new HTTP representation of the same application data.
Start With Read Endpoints
Add:
GET /api/products
GET /api/products/{id}
Return an explicit content type and stable shapes:
<?php
declare(strict_types=1);
function jsonResponse(array $payload, int $status = 200): never
{
http_response_code($status);
header('Content-Type: application/json; charset=utf-8');
echo json_encode($payload, JSON_THROW_ON_ERROR);
exit;
}
For a missing product, return a public error such as:
{"error":{"code":"product_not_found","message":"Product not found."}}
Do not expose exception text, SQL, stack traces, or internal filenames.
Add One Write Endpoint
Add POST /api/products after reads work. Decode with exceptions, validate the decoded shape, authorize the request, insert through the repository, and return 201 Created.
<?php
declare(strict_types=1);
try {
$payload = json_decode($rawBody, true, flags: JSON_THROW_ON_ERROR);
} catch (JsonException) {
jsonResponse([
'error' => ['code' => 'invalid_json', 'message' => 'Request body is not valid JSON.'],
], 400);
}
Malformed JSON and well-formed but invalid product data are different failures. Use a consistent validation error shape for the second case.
Keep Lists Bounded
Limit the list endpoint and make pagination visible before the catalog grows. Add authentication or a deliberate public/private decision for writes. Apply rate limiting where abuse would be costly.
Verify As A Client
Use curl to check list, found, missing, malformed JSON, validation failure, unauthorized create, and successful create cases.
Practice
Practice: Build A Product JSON API
Implement and verify the small JSON product API from the lesson using the existing repository.
Requirements
- Expose list, find, and create endpoints.
- Return JSON with an explicit content type.
- Use stable error shapes and appropriate HTTP status codes.
- Validate input and authorise writes.
- Handle malformed JSON deliberately.
- Do not leak exceptions or SQL in API responses.
- Keep pagination and rate limits visible for list endpoints.
Record the curl command, status code, and JSON shape for list, found, missing, malformed JSON, validation failure, unauthorized create, and successful create cases.
Show solution
- Checks authorization.
- Reads the raw request body.
- Decodes JSON with
JSON_THROW_ON_ERROR. - Validates
name,price_cents, andstatus. - Inserts through
ProductRepository. - Returns the created resource with
201.
Use one stable error shape:
{"error":{"code":"validation_failed","message":"Product data is invalid.","fields":{"name":"Enter a name."}}}
Run the required curl cases and compare both the HTTP status and JSON body. A client should never need to parse raw PHP errors.