Jednoduché API ve frameworku Slim 4 – č. 9 Přidání zboží uživatelům
- Jednoduché API ve frameworku Slim 4 – č. 1 Instalace
- Jednoduché API ve frameworku Slim 4 – č. 2 Základní CRUD
- Jednoduché API ve frameworku Slim 4 – č. 3 Struktura API a připojení k databázi
- Jednoduché API ve frameworku Slim 4 – č. 4 Testování funkcionality našeho malého API
- Jednoduché API ve frameworku Slim 4 – č. 5 Vylepšení UserControlleru
- Jednoduché API ve frameworku Slim 4 – č. 6 Přidání Model a Repositories
- Jednoduché API ve frameworku Slim 4 – č. 7 Validace dat
- Jednoduché API ve frameworku Slim 4 – č. 8 Přidáme si do datbáze produkty
- Jednoduché API ve frameworku Slim 4 – č. 9 Přidání zboží uživatelům
Aby mělo naše API konkrétní smysluplné použití přidáme si ještě endpointy ve kterých budeme jednotlivým uživatelům přiřazovat jejich nakoupené zboží.
Nejprve musíme přidat tabulku do naší databáze, která bude sloužit k uložení vazeb mezi produktem a uživatelem
1 2 3 4 5 6 7 8 |
CREATE TABLE user_products ( user_id INT NOT NULL, product_id INT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (user_id, product_id), FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE ); |
zase pokračujeme v naší zavedené struktuče vytvoříme si model, repository a controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?php namespace App\Models; class UserProduct { private int $userId; private int $productId; private string $createdAt; public function __construct(int $userId, int $productId, string $createdAt = null) { $this->userId = $userId; $this->productId = $productId; $this->createdAt = $createdAt ?? date('Y-m-d H:i:s'); } public function getUserId(): int { return $this->userId; } public function getProductId(): int { return $this->productId; } public function getCreatedAt(): string { return $this->createdAt; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
<?php namespace App\Repositories; use App\Models\UserProduct; use PDO; class UserProductRepository { private PDO $pdo; public function __construct(PDO $pdo) { $this->pdo = $pdo; } public function assignProducts(int $userId, array $productIds): bool { try { $this->pdo->beginTransaction(); $stmt = $this->pdo->prepare(" INSERT INTO user_products (user_id, product_id) VALUES (?, ?) ON DUPLICATE KEY UPDATE user_id = user_id "); foreach ($productIds as $productId) { $stmt->execute([$userId, $productId]); } $this->pdo->commit(); return true; } catch (\PDOException $e) { if ($this->pdo->inTransaction()) { $this->pdo->rollBack(); } throw $e; } } public function getUserProducts(int $userId): array { $stmt = $this->pdo->prepare(" SELECT up.user_id, up.product_id, up.created_at FROM user_products up WHERE up.user_id = ? "); $stmt->execute([$userId]); $userProducts = []; while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { $userProducts[] = new UserProduct( $row['user_id'], $row['product_id'], $row['created_at'] ); } return $userProducts; } public function removeProduct(int $userId, int $productId): bool { $stmt = $this->pdo->prepare(" DELETE FROM user_products WHERE user_id = ? AND product_id = ? "); $stmt->execute([$userId, $productId]); return $stmt->rowCount() > 0; } public function exists(int $userId, int $productId): bool { $stmt = $this->pdo->prepare(" SELECT 1 FROM user_products WHERE user_id = ? AND product_id = ? "); $stmt->execute([$userId, $productId]); return (bool) $stmt->fetch(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
<?php namespace App\Controllers; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use App\Repositories\UserRepository; use App\Repositories\ProductRepository; use App\Repositories\UserProductRepository; use App\Traits\JsonResponseTrait; class UserProductController { use JsonResponseTrait; public function __construct( private UserRepository $userRepository, private ProductRepository $productRepository, private UserProductRepository $userProductRepository ) {} public function assignProducts(Request $request, Response $response, array $args): Response { $userId = (int) $args['user_id']; $data = $request->getParsedBody(); $productIds = array_map('intval', $data['product_ids'] ?? []); try { // Kontrola existence uživatele if (!$this->userRepository->findById($userId)) { return $this->errorResponse($response, 'User not found', 404); } // Kontrola existence všech produktů foreach ($productIds as $productId) { if (!$this->productRepository->findById($productId)) { return $this->errorResponse($response, 'Product not found: ' . $productId, 404 ); } } // Přiřazení produktů $this->userProductRepository->assignProducts($userId, $productIds); // Získání přiřazených produktů $products = array_map( fn($id) => $this->productRepository->findById($id), $productIds ); return $this->successResponse($response, [ 'message' => 'Products assigned successfully', 'products' => $products ]); } catch (\Exception $e) { return $this->errorResponse( $response, 'Database error occurred', 500 ); } } public function getUserProducts(Request $request, Response $response, array $args): Response { $userId = (int) $args['user_id']; try { // Kontrola existence uživatele if (!$this->userRepository->findById($userId)) { return $this->errorResponse($response, 'User not found', 404); } // Získání vazeb user-product $userProducts = $this->userProductRepository->getUserProducts($userId); // Načtení detailů produktů $products = array_map( fn($up) => $this->productRepository->findById($up->getProductId()), $userProducts ); // Transformace produktů do pole $productsArray = array_map( fn($product) => [ 'id' => $product->getId(), 'name' => $product->getName(), 'description' => $product->getDescription(), 'price' => $product->getPrice(), 'created_at' => $product->getCreatedAt(), 'updated_at' => $product->getUpdatedAt() ], $products ); return $this->successResponse($response, $productsArray); } catch (\Exception $e) { return $this->errorResponse( $response, 'Database error occurred', 500 ); } } public function removeProduct(Request $request, Response $response, array $args): Response { $userId = (int) $args['user_id']; $productId = (int) $args['product_id']; try { // Kontrola existence vazby if (!$this->userProductRepository->exists($userId, $productId)) { return $this->errorResponse($response, 'Assignment not found', 404); } $this->userProductRepository->removeProduct($userId, $productId); return $this->successResponse($response, [ 'message' => 'Product removed from user successfully' ]); } catch (\Exception $e) { return $this->errorResponse( $response, 'Database error occurred', 500 ); } } } |
a samozřejmě musíme přidat routy pro naše nové endpointy
1 2 3 |
$app->post('/users/{user_id}/products', [UserProductController::class, 'assignProducts']); $app->get('/users/{user_id}/products', [UserProductController::class, 'getUserProducts']); $app->delete('/users/{user_id}/products/{product_id}', [UserProductController::class, 'removeProduct']); |