getContainer(); if ($container === null) { throw new RuntimeException('DI container is not configured'); } $json = static function (Response $response, mixed $data, int $status = 200): Response { $response->getBody()->write(json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); return $response ->withHeader('Content-Type', 'application/json') ->withStatus($status); }; $requiredFields = ['title', 'sku', 'stock', 'price', 'description', 'tagline']; $validate = static function (array $data) use ($requiredFields): ?string { foreach ($requiredFields as $field) { if (!isset($data[$field]) || $data[$field] === '') { return "Missing field: {$field}"; } } return null; }; $app->get('/', function (Request $request, Response $response) use ($json): Response { return $json($response, [ 'name' => 'Nerdshop API', 'endpoints' => [ 'GET /products', 'GET /products/{id}', 'POST /products', 'PUT /products/{id}', 'PATCH /products/{id}', 'DELETE /products/{id}', ], ]); }); // app.get('/products', (req,res) => { // const products = productManager.getAll(); // res.send(products); // }) $app->get('/products', function (Request $request, Response $response) use ($container, $json): Response { $repo = $container->get(ProductRepository::class); $items = array_map(static fn($product) => $product->toArray(), $repo->findAll()); return $json($response, $items); }); $app->get('/products/{id}', function (Request $request, Response $response, array $args) use ($container, $json): Response { $product = $container->get(ProductRepository::class)->findById($args['id']); if ($product === null) { return $json($response, ['error' => 'Product not found'], 404); } return $json($response, $product->toArray()); }); $app->post('/products', function (Request $request, Response $response) use ($container, $json, $validate): Response { $data = (array) $request->getParsedBody(); $error = $validate($data); if ($error !== null) { return $json($response, ['error' => $error], 400); } try { $product = $container->get(ProductRepository::class)->create($data); } catch (\PDOException $exception) { if ((int) $exception->getCode() === 23000) { return $json($response, ['error' => 'SKU already exists'], 409); } throw $exception; } return $json($response, $product->toArray(), 201); }); $app->put('/products/{id}', function (Request $request, Response $response, array $args) use ($container, $json, $validate): Response { $data = (array) $request->getParsedBody(); $error = $validate($data); if ($error !== null) { return $json($response, ['error' => $error], 400); } try { $product = $container->get(ProductRepository::class)->update($args['id'], $data); } catch (\PDOException $exception) { if ((int) $exception->getCode() === 23000) { return $json($response, ['error' => 'SKU already exists'], 409); } throw $exception; } if ($product === null) { return $json($response, ['error' => 'Product not found'], 404); } return $json($response, $product->toArray()); }); $app->patch('/products/{id}', function (Request $request, Response $response, array $args) use ($container, $json): Response { $data = (array) $request->getParsedBody(); $allowed = ['title', 'sku', 'stock', 'price', 'description', 'tagline']; $patch = array_intersect_key($data, array_flip($allowed)); if ($patch === []) { return $json($response, ['error' => 'No fields to update'], 400); } try { $product = $container->get(ProductRepository::class)->patch($args['id'], $patch); } catch (\PDOException $exception) { if ((int) $exception->getCode() === 23000) { return $json($response, ['error' => 'SKU already exists'], 409); } throw $exception; } if ($product === null) { return $json($response, ['error' => 'Product not found'], 404); } return $json($response, $product->toArray()); }); $app->delete('/products/{id}', function (Request $request, Response $response, array $args) use ($container, $json): Response { $deleted = $container->get(ProductRepository::class)->delete($args['id']); if (!$deleted) { return $json($response, ['error' => 'Product not found'], 404); } return $response->withStatus(204); }); };