Files
turborfq/public/index.php
Michael Chus 130f63f6b2 perf: убрано избыточное логирование при импорте для повышения производительности
- Удалено детальное логирование каждой строки импорта в PHP (error_log в циклах)
- Убраны console.log при парсинге и обработке CSV на фронтенде
- Оставлено только логирование начала/конца импорта и ошибок
- Значительно улучшена производительность при импорте больших файлов (тысячи строк)
2026-01-21 04:04:56 +03:00

258 lines
9.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
use DI\Container;
require __DIR__ . '/../vendor/autoload.php';
session_start();
// DIконтейнер
$container = new Container();
AppFactory::setContainer($container);
$app = AppFactory::create();
// В dev включаем подробные ошибки (можно выключить в проде)
$app->addErrorMiddleware(true, true, true);
$container->set('db', function () {
return \App\Db::connectFromSession();
});
// --- ROUTES ---
// Статическая страница с фронтендом
$app->get('/', function (Request $request, Response $response) {
// Очень простой view встроен прямо здесь
$html = file_get_contents(__DIR__ . '/index.html'); // вынесем в отдельный файл ниже
$response->getBody()->write($html);
return $response;
});
// Логин: сохраняет логин/пароль MariaDB в сессии после проверки
$app->post('/api/login', function (Request $request, Response $response) {
$data = json_decode((string)$request->getBody(), true);
$user = $data['user'] ?? '';
$pass = $data['pass'] ?? '';
try {
\App\Db::testConnection($user, $pass);
$_SESSION['db_user'] = $user;
$_SESSION['db_pass'] = $pass;
$payload = ['ok' => true];
$status = 200;
} catch (\RuntimeException $e) {
$payload = ['ok' => false, 'error' => $e->getMessage()];
$status = 401;
}
$response->getBody()->write(json_encode($payload));
return $response->withHeader('Content-Type', 'application/json')
->withStatus($status);
});
// Middleware на /api/*: проверяем, что аутентифицированы
$app->add(function (Request $request, $handler) {
$path = $request->getUri()->getPath();
if (str_starts_with($path, '/api/') && $path !== '/api/login') {
if (empty($_SESSION['db_user']) || empty($_SESSION['db_pass'])) {
$res = new \Slim\Psr7\Response();
$res->getBody()->write(json_encode(['error' => 'Not authenticated']));
return $res->withStatus(401)->withHeader('Content-Type', 'application/json');
}
}
return $handler->handle($request);
});
// API: дерево схем/таблиц
$app->get('/api/tree', function (Request $request, Response $response) use ($container) {
$pdo = $container->get('db');
$meta = new \App\MetaService($pdo);
$tree = $meta->getSchemaTree();
$response->getBody()->write(json_encode($tree));
return $response->withHeader('Content-Type', 'application/json');
});
// API: метаданные таблицы
$app->get('/api/table/meta', function (Request $request, Response $response) use ($container) {
$params = $request->getQueryParams();
$schema = $params['schema'] ?? '';
$table = $params['table'] ?? '';
$pdo = $container->get('db');
$meta = new \App\MetaService($pdo);
$data = $meta->getTableMeta($schema, $table);
$response->getBody()->write(json_encode($data));
return $response->withHeader('Content-Type', 'application/json');
});
// API: данные таблицы
$app->post('/api/table/data', function (Request $request, Response $response) use ($container) {
$payload = json_decode((string)$request->getBody(), true);
$schema = $payload['schema'] ?? '';
$table = $payload['table'] ?? '';
$page = (int)($payload['page'] ?? 1);
$pageSize = (int)($payload['pageSize'] ?? 50);
$filters = $payload['filters'] ?? [];
$sort = $payload['sort'] ?? null;
$columns = $payload['columns'] ?? [];
// ✅ Логирование для отладки
error_log("Data request: page=$page, pageSize=$pageSize, filters=" . json_encode($filters));
$pdo = $container->get('db');
$ds = new \App\DataService($pdo);
$resData = $ds->fetchData($schema, $table, $columns, $page, $pageSize, $filters, $sort);
// ✅ Логирование ответа
error_log("Data response: " . json_encode([
'data_count' => count($resData['data']),
'last_page' => $resData['last_page'],
'current_page' => $resData['current_page'],
'total' => $resData['total']
]));
$response->getBody()->write(json_encode($resData));
return $response->withHeader('Content-Type', 'application/json');
});
// API: insert / update / delete
$app->post('/api/table/insert', function (Request $request, Response $response) use ($container) {
$payload = json_decode((string)$request->getBody(), true);
$pdo = $container->get('db');
$meta = new \App\MetaService($pdo);
$ds = new \App\DataService($pdo);
$schema = $payload['schema'];
$table = $payload['table'];
$row = $payload['row'];
$metaArr = $meta->getTableMeta($schema, $table);
$result = $ds->insertRow($schema, $table, $row, $metaArr['columns']);
$response->getBody()->write(json_encode($result));
return $response->withHeader('Content-Type', 'application/json');
});
$app->post('/api/table/update', function (Request $request, Response $response) use ($container) {
$payload = json_decode((string)$request->getBody(), true);
$pdo = $container->get('db');
$meta = new \App\MetaService($pdo);
$ds = new \App\DataService($pdo);
$schema = $payload['schema'];
$table = $payload['table'];
$row = $payload['row'];
$metaArr = $meta->getTableMeta($schema, $table);
$result = $ds->updateRow($schema, $table, $row, $metaArr['columns'], $metaArr['primaryKey']);
$response->getBody()->write(json_encode($result));
return $response->withHeader('Content-Type', 'application/json');
});
$app->post('/api/table/delete', function (Request $request, Response $response) use ($container) {
$payload = json_decode((string)$request->getBody(), true);
$pdo = $container->get('db');
$meta = new \App\MetaService($pdo);
$ds = new \App\DataService($pdo);
$schema = $payload['schema'];
$table = $payload['table'];
$row = $payload['row'];
$metaArr = $meta->getTableMeta($schema, $table);
$result = $ds->deleteRow($schema, $table, $row, $metaArr['primaryKey']);
$response->getBody()->write(json_encode($result));
return $response->withHeader('Content-Type', 'application/json');
});
// API: импорт CSV (массовая вставка)
// API: импорт CSV (массовая вставка)
$app->post('/api/table/import-csv', function (Request $request, Response $response) use ($container) {
$body = (string)$request->getBody();
$payload = json_decode($body, true);
if (json_last_error() !== JSON_ERROR_NONE) {
error_log("CSV Import: Invalid JSON - " . json_last_error_msg());
$response->getBody()->write(json_encode(['error' => 'Invalid JSON: ' . json_last_error_msg()]));
return $response->withHeader('Content-Type', 'application/json')->withStatus(400);
}
$pdo = $container->get('db');
$meta = new \App\MetaService($pdo);
$ds = new \App\DataService($pdo);
$schema = $payload['schema'] ?? '';
$table = $payload['table'] ?? '';
$rows = $payload['rows'] ?? [];
if (empty($schema) || empty($table)) {
error_log("CSV Import: Missing schema or table");
$response->getBody()->write(json_encode(['error' => 'Schema and table are required']));
return $response->withHeader('Content-Type', 'application/json')->withStatus(400);
}
try {
$metaArr = $meta->getTableMeta($schema, $table);
$result = $ds->insertMultipleRows($schema, $table, $rows, $metaArr['columns']);
$response->getBody()->write(json_encode($result));
return $response->withHeader('Content-Type', 'application/json');
} catch (\Exception $e) {
error_log("CSV Import: Critical error - " . $e->getMessage());
$response->getBody()->write(json_encode([
'error' => $e->getMessage(),
'inserted' => 0,
'errors' => 1
]));
return $response->withHeader('Content-Type', 'application/json')->withStatus(500);
}
});
// API: экспорт CSV
$app->post('/api/table/export-csv', function (Request $request, Response $response) use ($container) {
$payload = json_decode((string)$request->getBody(), true);
$pdo = $container->get('db');
$ds = new \App\DataService($pdo);
$schema = $payload['schema'] ?? '';
$table = $payload['table'] ?? '';
$filters = $payload['filters'] ?? [];
$sort = $payload['sort'] ?? null;
$columns = $payload['columns'] ?? [];
$result = $ds->exportCSV($schema, $table, $columns, $filters, $sort);
$response->getBody()->write(json_encode($result));
return $response->withHeader('Content-Type', 'application/json');
});
// API: получить доступные значения для Foreign Key
$app->get('/api/fk-values', function (Request $request, Response $response) use ($container) {
$params = $request->getQueryParams();
$schema = $params['schema'] ?? '';
$table = $params['table'] ?? '';
$column = $params['column'] ?? '';
$pdo = $container->get('db');
// Получаем до 100 первых значений
$sql = "SELECT DISTINCT `{$column}` FROM `{$schema}`.`{$table}`
WHERE `{$column}` IS NOT NULL
ORDER BY `{$column}`
LIMIT 100";
$stmt = $pdo->prepare($sql);
$stmt->execute();
$values = $stmt->fetchAll(PDO::FETCH_COLUMN);
$response->getBody()->write(json_encode(['values' => $values]));
return $response->withHeader('Content-Type', 'application/json');
});
$app->run();