Split API and frontend, migrate SQLite to PostgreSQL
- api.fahrschultermin.de: full API entry point with CORS + session auth - fahrschultermin.de: frontend only, no more /api/v1 routing - Database.php: PostgreSQL support (pgsql driver + lastval()) - All repositories: use Database::lastInsertId() for PG compatibility - config/app.php: PostgreSQL connection settings + CORS config - bootstrap.php: pass full $config to Database::configure() - public/index.php: fetch-patch to redirect /api/v1 to api.fahrschultermin.de - database/schema_pgsql.sql: full PostgreSQL schema (BIGSERIAL) - database/import_pgsql.sql: 518 rows migrated from SQLite
This commit is contained in:
@@ -84,7 +84,7 @@ final class AppointmentRepository extends BaseRepository
|
||||
'updated_at' => $timestamp,
|
||||
]);
|
||||
|
||||
$appointmentId = (int) $this->db->lastInsertId();
|
||||
$appointmentId = (int) $this->lastInsertId();
|
||||
$this->replaceUnits($appointmentId, $data['units_breakdown'] ?? []);
|
||||
|
||||
return $this->find($tenantId, $appointmentId);
|
||||
|
||||
@@ -16,6 +16,11 @@ abstract class BaseRepository
|
||||
$this->db = Database::connection();
|
||||
}
|
||||
|
||||
protected function lastInsertId(): string
|
||||
{
|
||||
return Database::lastInsertId();
|
||||
}
|
||||
|
||||
protected function now(): string
|
||||
{
|
||||
return gmdate('c');
|
||||
|
||||
@@ -45,7 +45,7 @@ final class InstructorRepository extends BaseRepository
|
||||
'updated_at' => $timestamp,
|
||||
]);
|
||||
|
||||
return $this->find($tenantId, (int) $this->db->lastInsertId());
|
||||
return $this->find($tenantId, (int) $this->lastInsertId());
|
||||
}
|
||||
|
||||
public function update(int $tenantId, int $id, array $data): ?array
|
||||
|
||||
@@ -66,7 +66,7 @@ final class ReferenceDataRepository extends BaseRepository
|
||||
'created_at' => $timestamp,
|
||||
'updated_at' => $timestamp,
|
||||
]);
|
||||
$lessonTypeId = (int) $this->db->lastInsertId();
|
||||
$lessonTypeId = (int) $this->lastInsertId();
|
||||
$this->replaceLessonTypeVisibility($tenantId, $lessonTypeId, $data['visible_template_ids'] ?? null);
|
||||
|
||||
return $this->findLessonType($tenantId, $lessonTypeId);
|
||||
@@ -225,7 +225,7 @@ final class ReferenceDataRepository extends BaseRepository
|
||||
'created_at' => $timestamp,
|
||||
'updated_at' => $timestamp,
|
||||
]);
|
||||
$templateId = (int) $this->db->lastInsertId();
|
||||
$templateId = (int) $this->lastInsertId();
|
||||
|
||||
$this->replaceTemplateRequirements($templateId, $data['requirements'] ?? []);
|
||||
$this->attachTemplateToExistingStudentLessonTypes($tenantId, $templateId);
|
||||
|
||||
@@ -60,7 +60,7 @@ final class StudentRepository extends BaseRepository
|
||||
'updated_at' => $timestamp,
|
||||
]);
|
||||
|
||||
$studentId = (int) $this->db->lastInsertId();
|
||||
$studentId = (int) $this->lastInsertId();
|
||||
$this->snapshotRequirements($studentId, (int) $data['template_id']);
|
||||
|
||||
return $this->find($tenantId, $studentId);
|
||||
|
||||
@@ -40,7 +40,7 @@ final class TenantRepository extends BaseRepository
|
||||
'updated_at' => $timestamp,
|
||||
]);
|
||||
|
||||
return $this->find((int) $this->db->lastInsertId());
|
||||
return $this->find((int) $this->lastInsertId());
|
||||
}
|
||||
|
||||
public function update(int $id, array $data): ?array
|
||||
|
||||
@@ -74,7 +74,7 @@ final class UserRepository extends BaseRepository
|
||||
'updated_at' => $timestamp,
|
||||
]);
|
||||
|
||||
return $this->findById((int) $this->db->lastInsertId());
|
||||
return $this->findById((int) $this->lastInsertId());
|
||||
}
|
||||
|
||||
public function update(int $id, array $data): ?array
|
||||
|
||||
@@ -5,15 +5,17 @@ declare(strict_types=1);
|
||||
namespace App\Support;
|
||||
|
||||
use PDO;
|
||||
use PDOException;
|
||||
|
||||
final class Database
|
||||
{
|
||||
private static string $path;
|
||||
private static ?PDO $connection = null;
|
||||
private static array $config = [];
|
||||
|
||||
public static function configure(string $path): void
|
||||
public static function configure(array $config): void
|
||||
{
|
||||
self::$path = $path;
|
||||
self::$config = $config;
|
||||
self::$connection = null; // reset on reconfigure
|
||||
}
|
||||
|
||||
public static function connection(): PDO
|
||||
@@ -22,16 +24,43 @@ final class Database
|
||||
return self::$connection;
|
||||
}
|
||||
|
||||
$directory = dirname(self::$path);
|
||||
if (!is_dir($directory)) {
|
||||
mkdir($directory, 0775, true);
|
||||
$driver = self::$config['db_driver'] ?? 'sqlite';
|
||||
|
||||
if ($driver === 'pgsql') {
|
||||
$host = self::$config['db_host'] ?? '127.0.0.1';
|
||||
$port = self::$config['db_port'] ?? '5432';
|
||||
$dbname = self::$config['db_database'] ?? '';
|
||||
$user = self::$config['db_username'] ?? '';
|
||||
$password = self::$config['db_password'] ?? '';
|
||||
|
||||
$dsn = "pgsql:host={$host};port={$port};dbname={$dbname}";
|
||||
self::$connection = new PDO($dsn, $user, $password);
|
||||
} else {
|
||||
$path = self::$config['db_path'] ?? self::$config['db_path'] ?? '';
|
||||
$directory = dirname($path);
|
||||
if (!is_dir($directory)) {
|
||||
mkdir($directory, 0775, true);
|
||||
}
|
||||
self::$connection = new PDO('sqlite:' . $path);
|
||||
self::$connection->exec('PRAGMA foreign_keys = ON');
|
||||
}
|
||||
|
||||
self::$connection = new PDO('sqlite:' . self::$path);
|
||||
self::$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
self::$connection->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||
self::$connection->exec('PRAGMA foreign_keys = ON');
|
||||
|
||||
return self::$connection;
|
||||
}
|
||||
|
||||
public static function isPostgres(): bool
|
||||
{
|
||||
return (self::$config['db_driver'] ?? 'sqlite') === 'pgsql';
|
||||
}
|
||||
|
||||
public static function lastInsertId(): string
|
||||
{
|
||||
if (self::isPostgres()) {
|
||||
return self::$connection->query('SELECT lastval()')->fetchColumn();
|
||||
}
|
||||
return self::$connection->lastInsertId();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ if (!is_dir($sessionPath)) {
|
||||
session_save_path($sessionPath);
|
||||
session_start();
|
||||
|
||||
Database::configure($config['db_path']);
|
||||
Database::configure($config);
|
||||
|
||||
return [
|
||||
'config' => $config,
|
||||
|
||||
Reference in New Issue
Block a user