/
GTKerch
/
gantt
Обзор
Документация
Войти
/
GTKerch
/
gantt
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
api.php
228 строк
8 KB
GTKerch
Загрузить файлы в «»
20 май 2026, 09:16
Верифицирован
20 май 2026, 09:16
7fd2da8
Код
Авторство
О чём код?
<?php /** * api.php — REST API для диаграммы Ганта * Поддерживает: GET (список), POST (создание), PUT (редактирование), DELETE (удаление) */ define('DB_HOST', 'localhost'); define('DB_NAME', 'gantt_db'); define('DB_USER', 'root'); // ← замените на своего пользователя define('DB_PASS', ''); // ← замените на свой пароль define('DB_CHARSET', 'utf8mb4'); header('Content-Type: application/json; charset=UTF-8'); header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS'); header('Access-Control-Allow-Headers: Content-Type'); if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(204); exit; } function getConnection(): PDO { static $pdo = null; if ($pdo === null) { $dsn = sprintf( 'mysql:host=%s;dbname=%s;charset=%s', DB_HOST, DB_NAME, DB_CHARSET ); try { $pdo = new PDO($dsn, DB_USER, DB_PASS, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]); } catch (PDOException $e) { respond(500, ['error' => 'Ошибка подключения к БД: ' . $e->getMessage()]); } } return $pdo; } function respond(int $code, array $data): void { http_response_code($code); echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); exit; } function rowToTask(array $row): array { return [ 'id' => (int)$row['id'], 'name' => $row['name'], 'start' => $row['start_date'], 'end' => $row['end_date'], 'progress' => (int)$row['progress'], 'dependencies' => $row['dependencies'] ?? '', 'is_important' => (bool)$row['is_important'], 'created_at' => $row['created_at'], 'updated_at' => $row['updated_at'], ]; } function readBody(): array { $raw = file_get_contents('php://input'); if (empty($raw)) return []; $data = json_decode($raw, true); if (json_last_error() !== JSON_ERROR_NONE) { respond(400, ['error' => 'Некорректный JSON в теле запроса']); } return $data ?? []; } function validateTask(array $data, bool $requireAll = true): array { $errors = []; if ($requireAll || isset($data['name'])) { if (empty($data['name']) || !is_string($data['name'])) { $errors[] = 'Поле "name" обязательно и должно быть строкой'; } elseif (mb_strlen(trim($data['name'])) === 0) { $errors[] = 'Поле "name" не может быть пустым'; } } foreach (['start', 'end'] as $field) { if ($requireAll || isset($data[$field])) { if (empty($data[$field])) { $errors[] = "Поле \"$field\" обязательно"; } elseif (!preg_match('/^\d{4}-\d{2}-\d{2}/', $data[$field])) { $errors[] = "Поле \"$field\" должно быть датой формата YYYY-MM-DD"; } } } if ($requireAll || isset($data['progress'])) { $p = $data['progress'] ?? 0; if (!is_numeric($p) || (int)$p < 0 || (int)$p > 100) { $errors[] = 'Поле "progress" должно быть числом от 0 до 100'; } } return $errors; } $method = $_SERVER['REQUEST_METHOD']; $id = isset($_GET['id']) ? (int)$_GET['id'] : null; match ($method) { 'GET' => handleGet($id), 'POST' => handlePost(), 'PUT' => handlePut($id), 'DELETE' => handleDelete($id), default => respond(405, ['error' => 'Метод не поддерживается']), }; function handleGet(?int $id): void { $pdo = getConnection(); if ($id !== null) { $stmt = $pdo->prepare('SELECT * FROM tasks WHERE id = ?'); $stmt->execute([$id]); $row = $stmt->fetch(); if (!$row) respond(404, ['error' => "Задача #$id не найдена"]); respond(200, ['data' => rowToTask($row)]); } $stmt = $pdo->query('SELECT * FROM tasks ORDER BY start_date ASC, id ASC'); $tasks = array_map('rowToTask', $stmt->fetchAll()); respond(200, ['data' => $tasks, 'count' => count($tasks)]); } function handlePost(): void { $data = readBody(); $errors = validateTask($data, true); if ($errors) respond(422, ['errors' => $errors]); $start = substr($data['start'], 0, 10); $end = substr($data['end'], 0, 10); if ($end < $start) respond(422, ['errors' => ['Дата окончания не может быть раньше даты начала']]); $pdo = getConnection(); $stmt = $pdo->prepare( 'INSERT INTO tasks (name, start_date, end_date, progress, dependencies, is_important) VALUES (:name, :start, :end, :progress, :deps, :important)' ); $stmt->execute([ ':name' => trim($data['name']), ':start' => $start, ':end' => $end, ':progress' => (int)($data['progress'] ?? 0), ':deps' => !empty($data['dependencies']) ? $data['dependencies'] : null, ':important' => !empty($data['is_important']) ? 1 : 0, ]); $newId = (int)$pdo->lastInsertId(); $stmt2 = $pdo->prepare('SELECT * FROM tasks WHERE id = ?'); $stmt2->execute([$newId]); respond(201, ['message' => 'Задача создана', 'data' => rowToTask($stmt2->fetch())]); } function handlePut(?int $id): void { if (!$id) respond(400, ['error' => 'Укажите ?id= задачи для обновления']); $pdo = getConnection(); $stmt = $pdo->prepare('SELECT id FROM tasks WHERE id = ?'); $stmt->execute([$id]); if (!$stmt->fetch()) respond(404, ['error' => "Задача #$id не найдена"]); $data = readBody(); $errors = validateTask($data, false); if ($errors) respond(422, ['errors' => $errors]); $fields = []; $params = []; if (isset($data['name'])) { $fields[] = 'name = :name'; $params[':name'] = trim($data['name']); } if (isset($data['start'])) { $fields[] = 'start_date = :start'; $params[':start'] = substr($data['start'], 0, 10); } if (isset($data['end'])) { $fields[] = 'end_date = :end'; $params[':end'] = substr($data['end'], 0, 10); } if (isset($data['progress'])) { $fields[] = 'progress = :progress'; $params[':progress'] = (int)$data['progress']; } if (array_key_exists('dependencies', $data)) { $fields[] = 'dependencies = :deps'; $params[':deps'] = !empty($data['dependencies']) ? $data['dependencies'] : null; } if (isset($data['is_important'])) { $fields[] = 'is_important = :important'; $params[':important'] = $data['is_important'] ? 1 : 0; } if (empty($fields)) respond(400, ['error' => 'Нет полей для обновления']); if (isset($params[':start']) && isset($params[':end'])) { if ($params[':end'] < $params[':start']) { respond(422, ['errors' => ['Дата окончания не может быть раньше даты начала']]); } } $params[':id'] = $id; $sql = 'UPDATE tasks SET ' . implode(', ', $fields) . ' WHERE id = :id'; $pdo->prepare($sql)->execute($params); $stmt2 = $pdo->prepare('SELECT * FROM tasks WHERE id = ?'); $stmt2->execute([$id]); respond(200, ['message' => 'Задача обновлена', 'data' => rowToTask($stmt2->fetch())]); } function handleDelete(?int $id): void { if (!$id) respond(400, ['error' => 'Укажите ?id= задачи для удаления']); $pdo = getConnection(); $stmt = $pdo->prepare('SELECT id FROM tasks WHERE id = ?'); $stmt->execute([$id]); if (!$stmt->fetch()) respond(404, ['error' => "Задача #$id не найдена"]); $pdo->prepare('DELETE FROM tasks WHERE id = ?')->execute([$id]); respond(200, ['message' => "Задача #$id успешно удалена"]); }