slogan3

Maak een PHP-API voor gegevensuitwisseling

description

Met deze prompt kan de gebruiker een robuuste PHP-API ontwikkelen die data veilig en efficiënt uitwisselt, waardoor integratie met externe diensten eenvoudig wordt. Het bespaart tijd en biedt duidelijke richtlijnen voor best practices in API-ontwikkeling.

prompt

Help me bij het ontwerpen en implementeren van een PHP-API die data uitwisselt tussen mijn applicatie en externe systemen. Beschrijf hierbij hoe ik RE ...

try_prompt

generate_helper
disclaimerOnPageApi

ai_answers

provider: openai
model: gpt-4.1-nano
Natuurlijk! Hier is een overzicht van hoe je een PHP-API kunt ontwerpen en implementeren die data uitwisselt tussen jouw applicatie en externe systemen, inclusief RESTful endpoints, authenticatie en gegevensvalidatie voor productbeheer en voorraadbeheer. 1. Structuur van de API - Bestanden en mappen - `index.php` of een routerbestand voor het afhandelen van verzoeken - `api/` map met aparte bestanden voor elk resource zoals `producten.php` - `config/` voor configuratie en databaseverbinding - `models/` voor database-interacties - `auth/` voor authenticatie-logica - Database - Tabel `producten` met velden zoals `id`, `naam`, `beschrijving`, `prijs`, `voorraad`, `created_at`, `updated_at` 2. RESTful Endpoints Gebruik HTTP-methoden voor CRUD-operaties: - `GET /producten` — lijst alle producten - `GET /producten/{id}` — haal een specifiek product op - `POST /producten` — voeg een nieuw product toe - `PUT /producten/{id}` — werk een bestaand product bij - `DELETE /producten/{id}` — verwijder een product 3. Routing en verwerking - Gebruik bijvoorbeeld `.htaccess` of een routingbibliotheek om URLs te herschrijven - In `index.php` detecteer je de HTTP-verbinding en route je naar de juiste functie 4. Authenticatie - Implementatie van API-sleutels of Bearer tokens (bijv. JWT) - Voorbeeld: API-sleutel in headers (`Authorization: Bearer <token>`) - Validatie: controleer of de token geldig is voordat je gegevens verwerkt 5. Gegevensvalidatie - Controleer of alle verplichte velden aanwezig en correct zijn - Bijvoorbeeld: naam niet leeg, prijs numeriek en positief, voorraad integer - Gebruik PHP-functies of libraries zoals `filter_var()` en aangepaste validaties 6. Voorbeeldimplementatie (vereenvoudigd) ```php // index.php header('Content-Type: application/json'); // Verbind met database require 'config/database.php'; // Authenticatie $headers = apache_request_headers(); if (!isset($headers['Authorization'])) { http_response_code(401); echo json_encode(['error' => 'Geen authenticatieheader gevonden']); exit; } $authHeader = $headers['Authorization']; // Veronderstel Bearer token if (!preg_match('/Bearer\s(\S+)/', $authHeader, $matches)) { http_response_code(401); echo json_encode(['error' => 'Ongeldige authenticatie header']); exit; } $token = $matches[1]; // Controleer token (voorbeeld) if ($token !== 'jouw_secret_token') { http_response_code(403); echo json_encode(['error' => 'Ongeldige token']); exit; } // Routing $method = $_SERVER['REQUEST_METHOD']; $path = trim($_SERVER['PATH_INFO'], '/'); $parts = explode('/', $path); if ($parts[0] === 'producten') { require 'api/producten.php'; } else { http_response_code(404); echo json_encode(['error' => 'Niet gevonden']); } ``` ```php // api/producten.php switch ($method) { case 'GET': if (isset($parts[1])) { // Haal product op getProduct($pdo, $parts[1]); } else { // Haal alle producten op getAlleProducten($pdo); } break; case 'POST': addProduct($pdo); break; case 'PUT': if (isset($parts[1])) { updateProduct($pdo, $parts[1]); } break; case 'DELETE': if (isset($parts[1])) { deleteProduct($pdo, $parts[1]); } break; default: http_response_code(405); echo json_encode(['error' => 'Method niet toegestaan']); } function getAlleProducten($pdo) { // Query database $stmt = $pdo->query('SELECT * FROM producten'); $producten = $stmt->fetchAll(PDO::FETCH_ASSOC); echo json_encode($producten); } function getProduct($pdo, $id) { $stmt = $pdo->prepare('SELECT * FROM producten WHERE id = :id'); $stmt->execute([':id' => $id]); $product = $stmt->fetch(PDO::FETCH_ASSOC); if ($product) { echo json_encode($product); } else { http_response_code(404); echo json_encode(['error' => 'Product niet gevonden']); } } function addProduct($pdo) { $data = json_decode(file_get_contents('php://input'), true); // Validatie if (empty($data['naam']) || !is_numeric($data['prijs']) || !is_int($data['voorraad'])) { http_response_code(400); echo json_encode(['error' => 'Ongeldige gegevens']); return; } $stmt = $pdo->prepare('INSERT INTO producten (naam, beschrijving, prijs, voorraad) VALUES (:naam, :beschrijving, :prijs, :voorraad)'); $stmt->execute([ ':naam' => $data['naam'], ':beschrijving' => $data['beschrijving'] ?? '', ':prijs' => $data['prijs'], ':voorraad' => $data['voorraad'] ]); echo json_encode(['message' => 'Product toegevoegd', 'id' => $pdo->lastInsertId()]); } function updateProduct($pdo, $id) { $data = json_decode(file_get_contents('php://input'), true); // Validatie if (isset($data['naam']) && empty($data['naam'])) { http_response_code(400); echo json_encode(['error' => 'Naam mag niet leeg zijn']); return; } // Update query $sql = 'UPDATE producten SET '; $updates = []; $params = []; if (isset($data['naam'])) { $updates[] = 'naam = :naam'; $params[':naam'] = $data['naam']; } if (isset($data['beschrijving'])) { $updates[] = 'beschrijving = :beschrijving'; $params[':beschrijving'] = $data['beschrijving']; } if (isset($data['prijs'])) { if (!is_numeric($data['prijs'])) { http_response_code(400); echo json_encode(['error' => 'Ongeldig prijs']); return; } $updates[] = 'prijs = :prijs'; $params[':prijs'] = $data['prijs']; } if (isset($data['voorraad'])) { if (!is_int($data['voorraad'])) { http_response_code(400); echo json_encode(['error' => 'Ongeldige voorraad']); return; } $updates[] = 'voorraad = :voorraad'; $params[':voorraad'] = $data['voorraad']; } if (empty($updates)) { http_response_code(400); echo json_encode(['error' => 'Geen gegevens om bij te werken']); return; } $sql .= implode(', ', $updates) . ' WHERE id = :id'; $params[':id'] = $id; $stmt = $pdo->prepare($sql); $stmt->execute($params); echo json_encode(['message' => 'Product bijgewerkt']); } function deleteProduct($pdo, $id) { $stmt = $pdo->prepare('DELETE FROM producten WHERE id = :id'); $stmt->execute([':id' => $id]); echo json_encode(['message' => 'Product verwijderd']); } ``` 7. Voorraadbeheer - Bij het bijwerken van een product kun je de voorraad aanpassen - Mogelijkheid om voorraad te verhogen/verlagen via aparte endpoints of in de updatefunctie 8. Samenvatting - Gebruik RESTful principes voor duidelijke URLs en methoden - Implementeer token-gebaseerde authenticatie voor beveiliging - Valideer alle invoer streng om data-integriteit te waarborgen - Gebruik PDO voor veilige database-interacties (prepared statements) Met deze aanpak heb je een solide basis voor jouw PHP-API voor product- en voorraadbeheer.
provider: deepseek
model: deepseek-chat
Zeker, ik help je bij het ontwerpen en implementeren van een RESTful PHP-API voor productbeheer. Hier is een complete handleiding: ## 1. Projectstructuur ``` /api/ ├── config/ │ ├── database.php │ └── cors.php ├── controllers/ │ └── ProductController.php ├── models/ │ └── Product.php ├── middleware/ │ ├── AuthMiddleware.php │ └── ValidationMiddleware.php ├── routes/ │ └── api.php └── index.php ``` ## 2. RESTful Endpoints Ontwerp ```php // routes/api.php <?php use App\Controllers\ProductController; use App\Middleware\AuthMiddleware; use App\Middleware\ValidationMiddleware; // Product endpoints $app->get('/products', [ProductController::class, 'index']); $app->get('/products/{id}', [ProductController::class, 'show']); $app->post('/products', [ProductController::class, 'store'])->add(new AuthMiddleware())->add(new ValidationMiddleware()); $app->put('/products/{id}', [ProductController::class, 'update'])->add(new AuthMiddleware())->add(new ValidationMiddleware()); $app->delete('/products/{id}', [ProductController::class, 'destroy'])->add(new AuthMiddleware()); ``` ## 3. Authenticatie Implementatie (JWT) ```php // middleware/AuthMiddleware.php <?php namespace App\Middleware; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Server\RequestHandlerInterface as Handler; use Firebase\JWT\JWT; use Firebase\JWT\Key; class AuthMiddleware { public function __invoke(Request $request, Handler $handler) { $token = $request->getHeaderLine('Authorization'); if (empty($token)) { return new Response(401, ['Content-Type' => 'application/json'], json_encode(['error' => 'Authenticatie vereist'])); } try { $token = str_replace('Bearer ', '', $token); $decoded = JWT::decode($token, new Key($_ENV['JWT_SECRET'], 'HS256')); $request = $request->withAttribute('user_id', $decoded->user_id); return $handler->handle($request); } catch (\Exception $e) { return new Response(401, ['Content-Type' => 'application/json'], json_encode(['error' => 'Ongeldig token'])); } } } ``` ## 4. Gegevensvalidatie ```php // middleware/ValidationMiddleware.php <?php namespace App\Middleware; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Server\RequestHandlerInterface as Handler; class ValidationMiddleware { public function __invoke(Request $request, Handler $handler) { $data = $request->getParsedBody(); $errors = []; // Validatieregels voor product if (empty($data['naam'])) { $errors[] = 'Naam is verplicht'; } if (!isset($data['prijs']) || !is_numeric($data['prijs']) || $data['prijs'] <= 0) { $errors[] = 'Prijs moet een positief getal zijn'; } if (isset($data['voorraad']) && (!is_numeric($data['voorraad']) || $data['voorraad'] < 0)) { $errors[] = 'Voorraad moet een niet-negatief getal zijn'; } if (!empty($errors)) { return new Response(400, ['Content-Type' => 'application/json'], json_encode(['errors' => $errors])); } return $handler->handle($request); } } ``` ## 5. Product Controller ```php // controllers/ProductController.php <?php namespace App\Controllers; use App\Models\Product; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; class ProductController { public function index(Request $request, Response $response): Response { $products = Product::getAll(); $response->getBody()->write(json_encode($products)); return $response->withHeader('Content-Type', 'application/json'); } public function show(Request $request, Response $response, array $args): Response { $product = Product::find($args['id']); if (!$product) { $response->getBody()->write(json_encode(['error' => 'Product niet gevonden'])); return $response->withStatus(404)->withHeader('Content-Type', 'application/json'); } $response->getBody()->write(json_encode($product)); return $response->withHeader('Content-Type', 'application/json'); } public function store(Request $request, Response $response): Response { $data = $request->getParsedBody(); $productId = Product::create([ 'naam' => $data['naam'], 'beschrijving' => $data['beschrijving'] ?? '', 'prijs' => $data['prijs'], 'voorraad' => $data['voorraad'] ?? 0, 'categorie' => $data['categorie'] ?? '' ]); $response->getBody()->write(json_encode([ 'message' => 'Product toegevoegd', 'product_id' => $productId ])); return $response->withStatus(201)->withHeader('Content-Type', 'application/json'); } public function update(Request $request, Response $response, array $args): Response { $data = $request->getParsedBody(); $updated = Product::update($args['id'], $data); if (!$updated) { $response->getBody()->write(json_encode(['error' => 'Product niet gevonden'])); return $response->withStatus(404)->withHeader('Content-Type', 'application/json'); } $response->getBody()->write(json_encode(['message' => 'Product bijgewerkt'])); return $response->withHeader('Content-Type', 'application/json'); } public function destroy(Request $request, Response $response, array $args): Response { $deleted = Product::delete($args['id']); if (!$deleted) { $response->getBody()->write(json_encode(['error' => 'Product niet gevonden'])); return $response->withStatus(404)->withHeader('Content-Type', 'application/json'); } $response->getBody()->write(json_encode(['message' => 'Product verwijderd'])); return $response->withHeader('Content-Type', 'application/json'); } } ``` ## 6. Database Configuratie ```php // config/database.php <?php class Database { private static $connection = null; public static function getConnection() { if (self::$connection === null) { try { self::$connection = new PDO( "mysql:host=" . $_ENV['DB_HOST'] . ";dbname=" . $_ENV['DB_NAME'], $_ENV['DB_USER'], $_ENV['DB_PASS'] ); self::$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { die("Database connectie mislukt: " . $e->getMessage()); } } return self::$connection; } } ``` ## 7. Gebruik van de API **Producten ophalen:** ```bash GET /api/products ``` **Product toevoegen:** ```bash POST /api/products Authorization: Bearer <JWT_TOKEN> Content-Type: application/json { "naam": "iPhone 15", "prijs": 999.99, "voorraad": 50, "categorie": "Electronica" } ``` ## 8. Beveiligingstips 1. **HTTPS**: Gebruik altijd HTTPS in productie 2. **Rate Limiting**: Implementeer rate limiting voor misbruikpreventie 3. **Input Sanitization**: Sanitiseer alle gebruikersinput 4. **CORS**: Configureer CORS headers juist 5. **Error Handling**: Geef geen gevoelige informatie in errors ## 9. Benodigde Packages Installeer via Composer: ```bash composer require slim/slim composer require firebase/php-jwt composer require vlucas/phpdotenv ``` Dit ontwerp biedt een schaalbare, veilige RESTful API voor productbeheer met volledige CRUD-functionaliteit en voorraadbeheer.
error: Generation failed [deepseek] prompt_id=1236 locale=en err=DeepSeek connection/timeout