mysql Integration
This commit is contained in:
@@ -38,7 +38,7 @@ unter `saas-app/public/install/`.
|
||||
- `scripts/prepare-saas-env.php` legt aus `.env.example` eine lokale `.env` an.
|
||||
- `scripts/install-saas.php` fuehrt den lokalen Setup-Grundlauf aus.
|
||||
- `scripts/build-migration-bundle.php` baut die SQL-Migrationen zu einer Datei.
|
||||
- `scripts/run-sql-migrations.php` fuehrt die SQL-Migrationen direkt per PDO SQL Server aus.
|
||||
- `scripts/run-sql-migrations.php` fuehrt die SQL-Migrationen direkt per PDO fuer den konfigurierten DB-Treiber aus.
|
||||
|
||||
## Hinweise Zum Umbau
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ Der Installer kann:
|
||||
|
||||
- die `.env` speichern
|
||||
- das SQL-Bundle erzeugen
|
||||
- Migrationen direkt per PHP ausfuehren, wenn `pdo_sqlsrv` verfuegbar ist
|
||||
- Migrationen direkt per PHP ausfuehren, wenn die zum Treiber passende PDO-Erweiterung verfuegbar ist
|
||||
- sich nach erfolgreicher Einrichtung sperren
|
||||
|
||||
Die CLI-Skripte unter `scripts/*.php` bleiben als Alternative fuer lokale
|
||||
@@ -25,7 +25,7 @@ Vorbereitung oder Server mit Shell-Zugriff erhalten.
|
||||
|
||||
- PHP 8.2 oder neuer
|
||||
- Composer fuer den spaeteren Laravel-Bootstrap
|
||||
- SQL Server oder eine kompatible Datenbank fuer das Zielsystem
|
||||
- MySQL oder MariaDB fuer das Zielsystem
|
||||
- Webserver mit Document-Root auf `public/` des Zielprojekts
|
||||
- Cron-Zugang
|
||||
- optional: SMTP-Zugang fuer Mails
|
||||
@@ -38,7 +38,7 @@ Vorbereitung oder Server mit Shell-Zugriff erhalten.
|
||||
3. Mit `php scripts/prepare-saas-env.php` eine `.env` aus `.env.example` anlegen.
|
||||
4. Datenbankzugang, URL, Mail und Tenancy-Werte in `saas-app/.env` eintragen.
|
||||
5. Mit `php scripts/install-saas.php` das SQL-Bundle erzeugen.
|
||||
6. Das SQL-Bundle manuell in SQL Server ausfuehren oder mit `php scripts/run-sql-migrations.php --server=<server> --database=<db> --username=<user> --password=<pass>` direkt einspielen.
|
||||
6. Das SQL-Bundle manuell in MySQL/MariaDB importieren oder mit `php scripts/run-sql-migrations.php --connection=mysql --server=<server> --database=<db> --username=<user> --password=<pass>` direkt einspielen.
|
||||
7. Einen ersten Mandanten anlegen.
|
||||
8. Einen ersten Benutzer und eine Mitgliedszuordnung anlegen.
|
||||
9. Spaeter Composer und das eigentliche Laravel-Bootstrap nachziehen.
|
||||
@@ -49,12 +49,12 @@ Die aktuellen Dateien unter `saas-app/database/migrations/` sind SQL-Skizzen in
|
||||
PHP-Dateien, keine Laravel-Migrationsklassen. Deshalb gibt es aktuell bewusst
|
||||
kein `php artisan migrate`.
|
||||
|
||||
Stattdessen wird die SQL-Datei ueber Skripte erzeugt:
|
||||
Stattdessen wird die SQL-Datei passend zum konfigurierten DB-Treiber ueber Skripte erzeugt:
|
||||
|
||||
- Installationsvorbereitung inklusive SQL-Bundle:
|
||||
`php scripts/install-saas.php`
|
||||
- SQL direkt gegen SQL Server ausfuehren:
|
||||
`php scripts/run-sql-migrations.php --server=localhost --database=kaffeeliste_saas --username=sa --password=<passwort>`
|
||||
- SQL direkt gegen MySQL/MariaDB ausfuehren:
|
||||
`php scripts/run-sql-migrations.php --connection=mysql --server=localhost --database=kaffeeliste_saas --username=root --password=<passwort>`
|
||||
|
||||
Die erzeugte SQL-Datei liegt anschliessend unter:
|
||||
|
||||
@@ -76,6 +76,7 @@ Die wichtigsten Werte liegen in `saas-app/.env.example` und muessen fuer die
|
||||
eigene Umgebung angepasst werden:
|
||||
|
||||
- `APP_URL`
|
||||
- `DB_CONNECTION`
|
||||
- `DB_HOST`, `DB_DATABASE`, `DB_USERNAME`, `DB_PASSWORD`
|
||||
- `TENANCY_MODE`
|
||||
- `TENANCY_CENTRAL_DOMAINS`
|
||||
@@ -88,9 +89,22 @@ eigene Umgebung angepasst werden:
|
||||
1. Den Inhalt von `saas-app/` auf den Zielserver hochladen.
|
||||
2. Das Document-Root auf `public/` zeigen lassen.
|
||||
3. Schreibrechte fuer `saas-app/`, `.env`, `.installer.lock` und `database/migrations/generated/` sicherstellen.
|
||||
4. Den Installer unter `/install/` aufrufen und die Einrichtung durchfuehren.
|
||||
5. Nach erfolgreicher Einrichtung den Installer sperren.
|
||||
6. Die Anwendung einmal per Browser aufrufen und die Grundseiten pruefen.
|
||||
4. Sicherstellen, dass `open_basedir` nicht nur auf `public/` eingeschraenkt ist. PHP muss mindestens auf den kompletten Ordner `saas-app/` zugreifen duerfen, obwohl der Document-Root auf `public/` zeigt.
|
||||
5. Den Installer unter `/install/` aufrufen und die Einrichtung durchfuehren.
|
||||
6. Nach erfolgreicher Einrichtung den Installer sperren.
|
||||
7. Die Anwendung einmal per Browser aufrufen und die Grundseiten pruefen.
|
||||
|
||||
## MySQL Und MariaDB
|
||||
|
||||
Der aktuelle Installer ist jetzt auf MySQL/MariaDB ausgelegt:
|
||||
|
||||
- Standardwert `DB_CONNECTION=mysql`
|
||||
- Standardport `3306`
|
||||
- direkte PHP-Migration ueber `pdo_mysql`
|
||||
- SQL-Bundle im MySQL/MariaDB-Dialekt
|
||||
|
||||
Wenn `pdo_mysql` auf dem Hosting nicht geladen ist, kann das SQL-Bundle weiter
|
||||
manuell im Datenbank-Tool des Hosters importiert werden.
|
||||
|
||||
## Cron- und Batch-Betrieb
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ APP_URL=http://localhost
|
||||
LOG_CHANNEL=stack
|
||||
LOG_LEVEL=debug
|
||||
|
||||
DB_CONNECTION=sqlsrv
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=1433
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=kaffeeliste_saas
|
||||
DB_USERNAME=saas_user
|
||||
DB_PASSWORD=
|
||||
|
||||
+3
-3
@@ -31,7 +31,7 @@ Alternative mit PHP-CLI:
|
||||
|
||||
1. `php ../scripts/check-prerequisites.php`
|
||||
2. `php ../scripts/install-saas.php`
|
||||
3. `php ../scripts/run-sql-migrations.php --server=... --database=...`
|
||||
3. `php ../scripts/run-sql-migrations.php --connection=mysql --server=... --database=...`
|
||||
|
||||
## Migrationen
|
||||
|
||||
@@ -42,8 +42,8 @@ Skripte verarbeitet:
|
||||
- `..\scripts\build-migration-bundle.php`
|
||||
- `..\scripts\run-sql-migrations.php`
|
||||
|
||||
Wenn `pdo_sqlsrv` lokal nicht verfuegbar ist, muss das erzeugte SQL-Bundle
|
||||
manuell gegen SQL Server ausgefuehrt werden.
|
||||
Wenn `pdo_mysql` lokal oder auf dem Hosting nicht verfuegbar ist, muss das
|
||||
erzeugte SQL-Bundle manuell gegen MySQL/MariaDB ausgefuehrt werden.
|
||||
|
||||
## Migration Aus Dem Legacy-System
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
-- Generated migration bundle for Kaffeeliste SaaS
|
||||
-- Generated at 2026-03-21T19:24:13+00:00
|
||||
SET XACT_ABORT ON;
|
||||
BEGIN TRANSACTION;
|
||||
-- Generated at 2026-03-21T20:39:08+00:00
|
||||
-- Target: MySQL
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS=0;
|
||||
|
||||
-- Migration: 2026_03_20_000001_create_tenants_table.php
|
||||
CREATE TABLE tenants (
|
||||
@@ -12,7 +13,7 @@ CREATE TABLE tenants (
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL,
|
||||
UNIQUE (tenant_key)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000002_create_users_table.php
|
||||
CREATE TABLE users (
|
||||
@@ -20,11 +21,11 @@ CREATE TABLE users (
|
||||
email VARCHAR(255) NOT NULL,
|
||||
password_hash VARCHAR(255) NULL,
|
||||
display_name VARCHAR(255) NOT NULL,
|
||||
is_platform_admin BIT NOT NULL DEFAULT 0,
|
||||
is_platform_admin TINYINT(1) NOT NULL DEFAULT 0,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL,
|
||||
UNIQUE (email)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000003_create_tenant_users_table.php
|
||||
CREATE TABLE tenant_users (
|
||||
@@ -37,7 +38,7 @@ CREATE TABLE tenant_users (
|
||||
UNIQUE (tenant_id, user_id),
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id),
|
||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000004_create_roles_table.php
|
||||
CREATE TABLE roles (
|
||||
@@ -48,7 +49,7 @@ CREATE TABLE roles (
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL,
|
||||
UNIQUE (role_key, scope)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000005_create_tenant_user_roles_table.php
|
||||
CREATE TABLE tenant_user_roles (
|
||||
@@ -59,7 +60,7 @@ CREATE TABLE tenant_user_roles (
|
||||
UNIQUE (tenant_user_id, role_id),
|
||||
FOREIGN KEY (tenant_user_id) REFERENCES tenant_users(id),
|
||||
FOREIGN KEY (role_id) REFERENCES roles(id)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000006_create_members_table.php
|
||||
CREATE TABLE members (
|
||||
@@ -75,7 +76,7 @@ CREATE TABLE members (
|
||||
UNIQUE (tenant_id, tenant_user_id),
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id),
|
||||
FOREIGN KEY (tenant_user_id) REFERENCES tenant_users(id)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000006_create_password_reset_tokens_table.php
|
||||
CREATE TABLE password_reset_tokens (
|
||||
@@ -83,7 +84,7 @@ CREATE TABLE password_reset_tokens (
|
||||
token VARCHAR(255) NOT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
PRIMARY KEY (email)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000007_create_coffee_entries_table.php
|
||||
CREATE TABLE coffee_entries (
|
||||
@@ -99,7 +100,7 @@ CREATE TABLE coffee_entries (
|
||||
updated_at DATETIME NOT NULL,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id),
|
||||
FOREIGN KEY (member_id) REFERENCES members(id)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000007_create_tenant_identity_providers_table.php
|
||||
CREATE TABLE tenant_identity_providers (
|
||||
@@ -116,12 +117,12 @@ CREATE TABLE tenant_identity_providers (
|
||||
userinfo_url VARCHAR(1024) NULL,
|
||||
redirect_uri VARCHAR(1024) NOT NULL,
|
||||
scopes TEXT NULL,
|
||||
is_enabled BIT NOT NULL DEFAULT 1,
|
||||
is_enabled TINYINT(1) NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL,
|
||||
UNIQUE (tenant_id, provider_key),
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000008_create_payment_entries_table.php
|
||||
CREATE TABLE payment_entries (
|
||||
@@ -135,7 +136,7 @@ CREATE TABLE payment_entries (
|
||||
updated_at DATETIME NOT NULL,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id),
|
||||
FOREIGN KEY (member_id) REFERENCES members(id)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000008_create_user_identities_table.php
|
||||
CREATE TABLE user_identities (
|
||||
@@ -150,7 +151,7 @@ CREATE TABLE user_identities (
|
||||
UNIQUE (provider_key, external_subject),
|
||||
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000009_create_ledger_entries_table.php
|
||||
CREATE TABLE ledger_entries (
|
||||
@@ -166,7 +167,7 @@ CREATE TABLE ledger_entries (
|
||||
updated_at DATETIME NOT NULL,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id),
|
||||
FOREIGN KEY (member_id) REFERENCES members(id)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000010_create_announcements_table.php
|
||||
CREATE TABLE announcements (
|
||||
@@ -175,11 +176,11 @@ CREATE TABLE announcements (
|
||||
title VARCHAR(255) NOT NULL,
|
||||
message TEXT NOT NULL,
|
||||
visible_until DATETIME NULL,
|
||||
is_active BIT NOT NULL DEFAULT 1,
|
||||
is_active TINYINT(1) NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000011_create_faq_items_table.php
|
||||
CREATE TABLE faq_items (
|
||||
@@ -188,11 +189,11 @@ CREATE TABLE faq_items (
|
||||
question VARCHAR(255) NOT NULL,
|
||||
answer TEXT NOT NULL,
|
||||
sort_order INT NOT NULL DEFAULT 0,
|
||||
is_active BIT NOT NULL DEFAULT 1,
|
||||
is_active TINYINT(1) NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000012_create_surveys_table.php
|
||||
CREATE TABLE surveys (
|
||||
@@ -205,7 +206,7 @@ CREATE TABLE surveys (
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000013_create_survey_questions_table.php
|
||||
CREATE TABLE survey_questions (
|
||||
@@ -213,12 +214,12 @@ CREATE TABLE survey_questions (
|
||||
survey_id CHAR(36) NOT NULL,
|
||||
question TEXT NOT NULL,
|
||||
question_type VARCHAR(50) NOT NULL,
|
||||
is_required BIT NOT NULL DEFAULT 0,
|
||||
is_required TINYINT(1) NOT NULL DEFAULT 0,
|
||||
sort_order INT NOT NULL DEFAULT 0,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL,
|
||||
FOREIGN KEY (survey_id) REFERENCES surveys(id)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000014_create_survey_answers_table.php
|
||||
CREATE TABLE survey_answers (
|
||||
@@ -232,7 +233,7 @@ CREATE TABLE survey_answers (
|
||||
FOREIGN KEY (survey_id) REFERENCES surveys(id),
|
||||
FOREIGN KEY (question_id) REFERENCES survey_questions(id),
|
||||
FOREIGN KEY (tenant_user_id) REFERENCES tenant_users(id)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000015_create_import_jobs_table.php
|
||||
CREATE TABLE import_jobs (
|
||||
@@ -246,7 +247,7 @@ CREATE TABLE import_jobs (
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000016_create_export_jobs_table.php
|
||||
CREATE TABLE export_jobs (
|
||||
@@ -258,7 +259,7 @@ CREATE TABLE export_jobs (
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Migration: 2026_03_20_000017_create_notification_logs_table.php
|
||||
CREATE TABLE notification_logs (
|
||||
@@ -272,6 +273,6 @@ CREATE TABLE notification_logs (
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id)
|
||||
);
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
COMMIT TRANSACTION;
|
||||
SET FOREIGN_KEY_CHECKS=1;
|
||||
|
||||
@@ -50,8 +50,8 @@ $migrationSteps = [
|
||||
'Die Dateien unter `saas-app/database/migrations/*.php` sind keine Laravel-Migrationsklassen, sondern SQL-Skizzen.',
|
||||
'Das Bundle wird ueber `php scripts/build-migration-bundle.php` erzeugt.',
|
||||
'Empfohlener Weg: `php scripts/install-saas.php`.',
|
||||
'Direkte SQL-Server-Ausfuehrung: `php scripts/run-sql-migrations.php --server=<server> --database=<db> --username=<user> --password=<pass>`.',
|
||||
'Ohne `pdo_sqlsrv` die erzeugte SQL-Datei manuell in SQL Server Management Studio oder einem kompatiblen Tool ausfuehren.',
|
||||
'Direkte MySQL/MariaDB-Ausfuehrung: `php scripts/run-sql-migrations.php --connection=mysql --server=<server> --database=<db> --username=<user> --password=<pass>`.',
|
||||
'Ohne `pdo_mysql` die erzeugte SQL-Datei manuell im Datenbank-Tool des Hosters importieren.',
|
||||
];
|
||||
|
||||
function renderList(array $items): void
|
||||
@@ -380,7 +380,7 @@ function renderList(array $items): void
|
||||
<ul class="list">
|
||||
<li>Composer ist fuer den finalen Bootstrap weiterhin erforderlich.</li>
|
||||
<li>Die Migrationen sind aktuell SQL-basiert, nicht <code>artisan</code>-basiert.</li>
|
||||
<li>Fuer automatische Ausfuehrung wird die PHP-Erweiterung <code>pdo_sqlsrv</code> benoetigt.</li>
|
||||
<li>Fuer automatische Ausfuehrung auf MySQL/MariaDB wird die PHP-Erweiterung <code>pdo_mysql</code> benoetigt.</li>
|
||||
<li>Der bevorzugte Hosting-Pfad ist jetzt <code>/install/</code> als gefuehrter Einmal-Installer.</li>
|
||||
</ul>
|
||||
</article>
|
||||
|
||||
@@ -36,6 +36,56 @@ function scripts_installer_lock_path(): string
|
||||
return scripts_saas_app_path() . DIRECTORY_SEPARATOR . '.installer.lock';
|
||||
}
|
||||
|
||||
function scripts_supported_connections(): array
|
||||
{
|
||||
return [
|
||||
'mysql' => 'MySQL',
|
||||
'mariadb' => 'MariaDB',
|
||||
'sqlsrv' => 'SQL Server',
|
||||
];
|
||||
}
|
||||
|
||||
function scripts_normalize_db_connection(?string $connection): string
|
||||
{
|
||||
$normalized = strtolower(trim((string) $connection));
|
||||
|
||||
if ($normalized === 'maria' || $normalized === 'maria-db') {
|
||||
$normalized = 'mariadb';
|
||||
}
|
||||
|
||||
if ($normalized === 'sqlserver' || $normalized === 'mssql') {
|
||||
$normalized = 'sqlsrv';
|
||||
}
|
||||
|
||||
return array_key_exists($normalized, scripts_supported_connections()) ? $normalized : 'mysql';
|
||||
}
|
||||
|
||||
function scripts_connection_label(string $connection): string
|
||||
{
|
||||
$connection = scripts_normalize_db_connection($connection);
|
||||
$supported = scripts_supported_connections();
|
||||
|
||||
return $supported[$connection];
|
||||
}
|
||||
|
||||
function scripts_default_db_port(string $connection): string
|
||||
{
|
||||
$connection = scripts_normalize_db_connection($connection);
|
||||
|
||||
if ($connection === 'sqlsrv') {
|
||||
return '1433';
|
||||
}
|
||||
|
||||
return '3306';
|
||||
}
|
||||
|
||||
function scripts_required_pdo_extension(string $connection): string
|
||||
{
|
||||
$connection = scripts_normalize_db_connection($connection);
|
||||
|
||||
return $connection === 'sqlsrv' ? 'pdo_sqlsrv' : 'pdo_mysql';
|
||||
}
|
||||
|
||||
function scripts_parent_directory(string $path): string
|
||||
{
|
||||
return dirname($path);
|
||||
@@ -215,8 +265,85 @@ function scripts_format_env_value(string $value): string
|
||||
return $value;
|
||||
}
|
||||
|
||||
function scripts_build_migration_bundle(?string $outputPath = null): string
|
||||
function scripts_transform_migration_sql(string $sql, string $connection): string
|
||||
{
|
||||
$connection = scripts_normalize_db_connection($connection);
|
||||
$sql = trim(str_replace(["\r\n", "\r"], "\n", $sql));
|
||||
|
||||
if ($connection === 'sqlsrv') {
|
||||
return $sql;
|
||||
}
|
||||
|
||||
$sql = preg_replace('/\bBIT\s+NOT NULL\s+DEFAULT\s+([01])\b/i', 'TINYINT(1) NOT NULL DEFAULT $1', $sql) ?? $sql;
|
||||
$sql = preg_replace('/\bBIT\b/i', 'TINYINT(1)', $sql) ?? $sql;
|
||||
|
||||
if (preg_match('/^CREATE TABLE\s+/i', $sql) === 1) {
|
||||
$sql = preg_replace(
|
||||
'/\)\s*;\s*$/',
|
||||
') ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;',
|
||||
$sql
|
||||
) ?? $sql;
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
function scripts_load_migration_sql(string $file, string $connection): string
|
||||
{
|
||||
$sql = require $file;
|
||||
|
||||
if (!is_string($sql) || trim($sql) === '') {
|
||||
throw new RuntimeException('Ungueltige Migration: ' . $file);
|
||||
}
|
||||
|
||||
return scripts_transform_migration_sql($sql, $connection);
|
||||
}
|
||||
|
||||
function scripts_bundle_prologue(string $connection): array
|
||||
{
|
||||
$connection = scripts_normalize_db_connection($connection);
|
||||
|
||||
if ($connection === 'sqlsrv') {
|
||||
return [
|
||||
'-- Generated migration bundle for Kaffeeliste SaaS',
|
||||
'-- Generated at ' . date('c'),
|
||||
'-- Target: ' . scripts_connection_label($connection),
|
||||
'SET XACT_ABORT ON;',
|
||||
'BEGIN TRANSACTION;',
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'-- Generated migration bundle for Kaffeeliste SaaS',
|
||||
'-- Generated at ' . date('c'),
|
||||
'-- Target: ' . scripts_connection_label($connection),
|
||||
'SET NAMES utf8mb4;',
|
||||
'SET FOREIGN_KEY_CHECKS=0;',
|
||||
];
|
||||
}
|
||||
|
||||
function scripts_bundle_epilogue(string $connection): array
|
||||
{
|
||||
$connection = scripts_normalize_db_connection($connection);
|
||||
|
||||
if ($connection === 'sqlsrv') {
|
||||
return [
|
||||
'',
|
||||
'COMMIT TRANSACTION;',
|
||||
'',
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'',
|
||||
'SET FOREIGN_KEY_CHECKS=1;',
|
||||
'',
|
||||
];
|
||||
}
|
||||
|
||||
function scripts_build_migration_bundle(?string $outputPath = null, string $connection = 'mysql'): string
|
||||
{
|
||||
$connection = scripts_normalize_db_connection($connection);
|
||||
$migrationDir = scripts_saas_app_path()
|
||||
. DIRECTORY_SEPARATOR . 'database'
|
||||
. DIRECTORY_SEPARATOR . 'migrations';
|
||||
@@ -241,27 +368,19 @@ function scripts_build_migration_bundle(?string $outputPath = null): string
|
||||
throw new RuntimeException('Ausgabeverzeichnis konnte nicht erstellt werden: ' . $outputDir);
|
||||
}
|
||||
|
||||
$bundle = [];
|
||||
$bundle[] = '-- Generated migration bundle for Kaffeeliste SaaS';
|
||||
$bundle[] = '-- Generated at ' . date('c');
|
||||
$bundle[] = 'SET XACT_ABORT ON;';
|
||||
$bundle[] = 'BEGIN TRANSACTION;';
|
||||
$bundle = scripts_bundle_prologue($connection);
|
||||
|
||||
foreach ($files as $file) {
|
||||
$sql = require $file;
|
||||
|
||||
if (!is_string($sql) || trim($sql) === '') {
|
||||
throw new RuntimeException('Ungueltige Migration: ' . $file);
|
||||
}
|
||||
$sql = scripts_load_migration_sql($file, $connection);
|
||||
|
||||
$bundle[] = '';
|
||||
$bundle[] = '-- Migration: ' . basename($file);
|
||||
$bundle[] = trim($sql);
|
||||
$bundle[] = $sql;
|
||||
}
|
||||
|
||||
$bundle[] = '';
|
||||
$bundle[] = 'COMMIT TRANSACTION;';
|
||||
$bundle[] = '';
|
||||
foreach (scripts_bundle_epilogue($connection) as $line) {
|
||||
$bundle[] = $line;
|
||||
}
|
||||
|
||||
if (file_put_contents($outputPath, implode(PHP_EOL, $bundle)) === false) {
|
||||
throw new RuntimeException('Das SQL-Bundle konnte nicht geschrieben werden: ' . $outputPath);
|
||||
@@ -272,9 +391,10 @@ function scripts_build_migration_bundle(?string $outputPath = null): string
|
||||
|
||||
function scripts_run_sql_migrations(array $config): array
|
||||
{
|
||||
$connection = scripts_normalize_db_connection(isset($config['connection']) ? (string) $config['connection'] : 'mysql');
|
||||
$server = isset($config['server']) ? $config['server'] : null;
|
||||
$database = isset($config['database']) ? $config['database'] : null;
|
||||
$port = isset($config['port']) ? (string) $config['port'] : '1433';
|
||||
$port = isset($config['port']) ? (string) $config['port'] : scripts_default_db_port($connection);
|
||||
$username = isset($config['username']) ? $config['username'] : null;
|
||||
$password = isset($config['password']) ? $config['password'] : null;
|
||||
|
||||
@@ -282,8 +402,9 @@ function scripts_run_sql_migrations(array $config): array
|
||||
throw new RuntimeException('Bitte Server und Datenbank angeben.');
|
||||
}
|
||||
|
||||
if (!extension_loaded('pdo_sqlsrv')) {
|
||||
throw new RuntimeException('Die PHP-Erweiterung pdo_sqlsrv ist nicht geladen.');
|
||||
$requiredExtension = scripts_required_pdo_extension($connection);
|
||||
if (!extension_loaded($requiredExtension)) {
|
||||
throw new RuntimeException('Die PHP-Erweiterung ' . $requiredExtension . ' ist nicht geladen.');
|
||||
}
|
||||
|
||||
$migrationDir = scripts_saas_app_path()
|
||||
@@ -297,33 +418,53 @@ function scripts_run_sql_migrations(array $config): array
|
||||
throw new RuntimeException('Keine Migrationsdateien gefunden.');
|
||||
}
|
||||
|
||||
$dsn = sprintf('sqlsrv:Server=%s,%s;Database=%s;TrustServerCertificate=1', $server, $port, $database);
|
||||
$pdo = new PDO($dsn, $username, $password, [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
]);
|
||||
|
||||
$pdo->beginTransaction();
|
||||
if ($connection === 'sqlsrv') {
|
||||
$dsn = sprintf('sqlsrv:Server=%s,%s;Database=%s;TrustServerCertificate=1', $server, $port, $database);
|
||||
$pdo = new PDO($dsn, $username, $password, [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
]);
|
||||
} else {
|
||||
$dsn = sprintf('mysql:host=%s;port=%s;dbname=%s;charset=utf8mb4', $server, $port, $database);
|
||||
$pdo = new PDO($dsn, $username, $password, [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
]);
|
||||
}
|
||||
|
||||
$executed = [];
|
||||
|
||||
try {
|
||||
foreach ($files as $file) {
|
||||
$sql = require $file;
|
||||
if ($connection === 'sqlsrv') {
|
||||
$pdo->beginTransaction();
|
||||
} else {
|
||||
$pdo->exec('SET NAMES utf8mb4');
|
||||
$pdo->exec('SET FOREIGN_KEY_CHECKS=0');
|
||||
}
|
||||
|
||||
if (!is_string($sql) || trim($sql) === '') {
|
||||
throw new RuntimeException('Ungueltige Migration: ' . basename($file));
|
||||
}
|
||||
foreach ($files as $file) {
|
||||
$sql = scripts_load_migration_sql($file, $connection);
|
||||
|
||||
$pdo->exec($sql);
|
||||
$executed[] = basename($file);
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
if ($connection === 'sqlsrv') {
|
||||
$pdo->commit();
|
||||
} else {
|
||||
$pdo->exec('SET FOREIGN_KEY_CHECKS=1');
|
||||
}
|
||||
} catch (Throwable $exception) {
|
||||
if ($pdo->inTransaction()) {
|
||||
$pdo->rollBack();
|
||||
}
|
||||
|
||||
if ($connection !== 'sqlsrv') {
|
||||
try {
|
||||
$pdo->exec('SET FOREIGN_KEY_CHECKS=1');
|
||||
} catch (Throwable $ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,10 +33,12 @@ if (!isset($_SESSION['installer_csrf'])) {
|
||||
|
||||
$defaults = scripts_read_env_file(scripts_env_example_path());
|
||||
$currentEnv = scripts_read_env_file(scripts_env_path());
|
||||
$defaultConnection = scripts_normalize_db_connection($currentEnv['DB_CONNECTION'] ?? ($defaults['DB_CONNECTION'] ?? 'mysql'));
|
||||
$values = [
|
||||
'APP_URL' => $currentEnv['APP_URL'] ?? ($defaults['APP_URL'] ?? ''),
|
||||
'DB_CONNECTION' => $defaultConnection,
|
||||
'DB_HOST' => $currentEnv['DB_HOST'] ?? ($defaults['DB_HOST'] ?? '127.0.0.1'),
|
||||
'DB_PORT' => $currentEnv['DB_PORT'] ?? ($defaults['DB_PORT'] ?? '1433'),
|
||||
'DB_PORT' => $currentEnv['DB_PORT'] ?? ($defaults['DB_PORT'] ?? scripts_default_db_port($defaultConnection)),
|
||||
'DB_DATABASE' => $currentEnv['DB_DATABASE'] ?? ($defaults['DB_DATABASE'] ?? ''),
|
||||
'DB_USERNAME' => $currentEnv['DB_USERNAME'] ?? ($defaults['DB_USERNAME'] ?? ''),
|
||||
'DB_PASSWORD' => '',
|
||||
@@ -64,6 +66,15 @@ $openBaseDir = (string) ini_get('open_basedir');
|
||||
$envPathState = scripts_path_writable_state(scripts_env_path());
|
||||
$lockPathState = scripts_path_writable_state(scripts_installer_lock_path());
|
||||
$bundlePathState = scripts_path_writable_state(scripts_bundle_output_path());
|
||||
$activeConnection = scripts_normalize_db_connection($values['DB_CONNECTION']);
|
||||
$activeConnectionLabel = scripts_connection_label($activeConnection);
|
||||
$requiredExtension = scripts_required_pdo_extension($activeConnection);
|
||||
$requiredExtensionLoaded = extension_loaded($requiredExtension);
|
||||
|
||||
if (!$saasAppVisible) {
|
||||
$errors[] = 'PHP darf den SaaS-App-Ordner aktuell nicht lesen. Die `open_basedir`-Konfiguration erlaubt nur `public/`.';
|
||||
$errors[] = 'Stelle den Document-Root weiter auf `saas-app/public`, erweitere aber `open_basedir` mindestens auf `saas-app/`.';
|
||||
}
|
||||
|
||||
if ($requestMethod === 'POST' && !$locked) {
|
||||
$csrf = (string) ($_POST['csrf'] ?? '');
|
||||
@@ -77,6 +88,17 @@ if ($requestMethod === 'POST' && !$locked) {
|
||||
}
|
||||
}
|
||||
|
||||
$values['DB_CONNECTION'] = scripts_normalize_db_connection($values['DB_CONNECTION']);
|
||||
|
||||
if ($values['DB_PORT'] === '') {
|
||||
$values['DB_PORT'] = scripts_default_db_port($values['DB_CONNECTION']);
|
||||
}
|
||||
|
||||
$activeConnection = scripts_normalize_db_connection($values['DB_CONNECTION']);
|
||||
$activeConnectionLabel = scripts_connection_label($activeConnection);
|
||||
$requiredExtension = scripts_required_pdo_extension($activeConnection);
|
||||
$requiredExtensionLoaded = extension_loaded($requiredExtension);
|
||||
|
||||
$values['OIDC_ENABLED'] = isset($_POST['OIDC_ENABLED']) ? 'true' : 'false';
|
||||
|
||||
if ($values['DB_PASSWORD'] === '' && isset($currentEnv['DB_PASSWORD'])) {
|
||||
@@ -98,18 +120,19 @@ if ($requestMethod === 'POST' && !$locked) {
|
||||
scripts_write_env_file($values);
|
||||
$messages[] = '.env wurde geschrieben.';
|
||||
|
||||
$bundlePath = scripts_build_migration_bundle();
|
||||
$messages[] = 'SQL-Bundle wurde erzeugt.';
|
||||
$bundlePath = scripts_build_migration_bundle(null, $values['DB_CONNECTION']);
|
||||
$messages[] = 'SQL-Bundle fuer ' . scripts_connection_label($values['DB_CONNECTION']) . ' wurde erzeugt.';
|
||||
|
||||
if (isset($_POST['run_migrations'])) {
|
||||
$executedMigrations = scripts_run_sql_migrations([
|
||||
'connection' => $values['DB_CONNECTION'],
|
||||
'server' => $values['DB_HOST'],
|
||||
'database' => $values['DB_DATABASE'],
|
||||
'port' => $values['DB_PORT'],
|
||||
'username' => $values['DB_USERNAME'],
|
||||
'password' => $values['DB_PASSWORD'],
|
||||
]);
|
||||
$messages[] = 'Migrationen wurden direkt ueber PHP ausgefuehrt.';
|
||||
$messages[] = 'Migrationen wurden direkt ueber PHP fuer ' . $activeConnectionLabel . ' ausgefuehrt.';
|
||||
}
|
||||
|
||||
if (isset($_POST['lock_installer'])) {
|
||||
@@ -123,8 +146,8 @@ if ($requestMethod === 'POST' && !$locked) {
|
||||
} catch (Throwable $exception) {
|
||||
$message = $exception->getMessage();
|
||||
|
||||
if (scripts_string_contains($message, 'pdo_sqlsrv')) {
|
||||
$errors[] = 'Migrationen konnten nicht direkt ueber PHP ausgefuehrt werden. Bitte `pdo_sqlsrv` pruefen oder das SQL-Bundle manuell importieren.';
|
||||
if (scripts_string_contains($message, 'pdo_')) {
|
||||
$errors[] = 'Migrationen konnten nicht direkt ueber PHP ausgefuehrt werden. Bitte `' . $requiredExtension . '` pruefen oder das SQL-Bundle manuell importieren.';
|
||||
} elseif (scripts_string_contains($message, '.env')) {
|
||||
$errors[] = 'Die Konfiguration konnte nicht gespeichert werden. Zielpfad: ' . scripts_env_path();
|
||||
$errors[] = 'Status fuer .env: ' . scripts_path_state_label($envPathState) . '. Elternordner: ' . $envPathState['parent'];
|
||||
@@ -352,6 +375,14 @@ function h(string $value): string
|
||||
<label for="APP_URL">APP_URL</label>
|
||||
<input id="APP_URL" name="APP_URL" value="<?= h($values['APP_URL']) ?>" required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="DB_CONNECTION">DB_CONNECTION</label>
|
||||
<select id="DB_CONNECTION" name="DB_CONNECTION">
|
||||
<?php foreach (scripts_supported_connections() as $connectionKey => $connectionLabel): ?>
|
||||
<option value="<?= h($connectionKey) ?>"<?= $values['DB_CONNECTION'] === $connectionKey ? ' selected' : '' ?>><?= h($connectionLabel) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="DB_HOST">DB_HOST</label>
|
||||
<input id="DB_HOST" name="DB_HOST" value="<?= h($values['DB_HOST']) ?>" required>
|
||||
@@ -426,8 +457,8 @@ function h(string $value): string
|
||||
|
||||
<div class="stack">
|
||||
<label class="checkbox">
|
||||
<input name="run_migrations" type="checkbox"<?= extension_loaded('pdo_sqlsrv') ? '' : ' disabled' ?>>
|
||||
<span>Migrationen direkt ueber PHP ausfuehren<?= extension_loaded('pdo_sqlsrv') ? '' : ' (pdo_sqlsrv fehlt aktuell)' ?></span>
|
||||
<input name="run_migrations" type="checkbox"<?= $requiredExtensionLoaded ? '' : ' disabled' ?>>
|
||||
<span>Migrationen direkt ueber PHP fuer <?= h($activeConnectionLabel) ?> ausfuehren<?= $requiredExtensionLoaded ? '' : ' (' . h($requiredExtension) . ' fehlt aktuell)' ?></span>
|
||||
</label>
|
||||
<label class="checkbox">
|
||||
<input name="lock_installer" type="checkbox" checked>
|
||||
@@ -452,13 +483,15 @@ function h(string $value): string
|
||||
<li>SaaS-App Pfad: <code><?= h($saasAppPath) ?></code></li>
|
||||
<li>SaaS-App sichtbar: <code><?= $saasAppVisible ? 'ja' : 'nein' ?></code></li>
|
||||
<li>open_basedir: <code><?= h($openBaseDir !== '' ? $openBaseDir : 'nicht gesetzt') ?></code></li>
|
||||
<li>DB_CONNECTION: <code><?= h($activeConnection) ?></code></li>
|
||||
<li>Ziel-Datenbank: <code><?= h($activeConnectionLabel) ?></code></li>
|
||||
<li>.env.example: <code><?= is_file(scripts_env_example_path()) ? 'vorhanden' : 'fehlt' ?></code></li>
|
||||
<li>.env: <code><?= is_file(scripts_env_path()) ? 'vorhanden' : 'fehlt' ?></code></li>
|
||||
<li>.env Status: <code><?= h(scripts_path_state_label($envPathState)) ?></code></li>
|
||||
<li>.env Zielpfad: <code><?= h($envPathState['path']) ?></code></li>
|
||||
<li>.env Elternordner: <code><?= h($envPathState['parent']) ?></code></li>
|
||||
<li>.env Elternordner beschreibbar: <code><?= $envPathState['parent_writable'] ? 'ja' : 'nein' ?></code></li>
|
||||
<li>pdo_sqlsrv: <code><?= extension_loaded('pdo_sqlsrv') ? 'aktiv' : 'nicht geladen' ?></code></li>
|
||||
<li><?= h($requiredExtension) ?>: <code><?= $requiredExtensionLoaded ? 'aktiv' : 'nicht geladen' ?></code></li>
|
||||
<li>Installer-Lock: <code><?= $locked ? 'aktiv' : 'offen' ?></code></li>
|
||||
<li>Lock-Datei Status: <code><?= h(scripts_path_state_label($lockPathState)) ?></code></li>
|
||||
<li>Bundle-Pfad: <code><?= h(scripts_bundle_output_path()) ?></code></li>
|
||||
|
||||
@@ -4,10 +4,21 @@ declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/support.php';
|
||||
|
||||
$outputPath = $argv[1] ?? scripts_bundle_output_path();
|
||||
$options = scripts_parse_options($argv);
|
||||
$outputPath = scripts_bundle_output_path();
|
||||
$connection = scripts_normalize_db_connection($options['connection'] ?? scripts_read_env_file(scripts_env_path())['DB_CONNECTION'] ?? 'mysql');
|
||||
|
||||
foreach (array_slice($argv, 1) as $arg) {
|
||||
if (scripts_string_starts_with($arg, '--')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$outputPath = $arg;
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
scripts_stdout(scripts_build_migration_bundle($outputPath));
|
||||
scripts_stdout(scripts_build_migration_bundle($outputPath, $connection));
|
||||
} catch (Throwable $exception) {
|
||||
scripts_stderr($exception->getMessage());
|
||||
}
|
||||
|
||||
@@ -7,7 +7,11 @@ require_once __DIR__ . '/support.php';
|
||||
$phpVersion = PHP_VERSION;
|
||||
$composerExists = scripts_check_command('composer');
|
||||
$gitExists = scripts_check_command('git');
|
||||
$env = scripts_read_env_file(scripts_env_path());
|
||||
$dbConnection = scripts_normalize_db_connection($env['DB_CONNECTION'] ?? 'mysql');
|
||||
$pdoMysqlLoaded = extension_loaded('pdo_mysql');
|
||||
$pdoSqlsrvLoaded = extension_loaded('pdo_sqlsrv');
|
||||
$requiredExtension = scripts_required_pdo_extension($dbConnection);
|
||||
|
||||
scripts_stdout('Pruefe lokale Voraussetzungen fuer Kaffeeliste SaaS...');
|
||||
scripts_stdout('Projektwurzel: ' . scripts_project_root());
|
||||
@@ -17,7 +21,10 @@ $checks = [
|
||||
['PHP', true, $phpVersion],
|
||||
['Composer', $composerExists, $composerExists ? 'verfuegbar' : 'nicht gefunden'],
|
||||
['Git', $gitExists, $gitExists ? 'verfuegbar' : 'nicht gefunden'],
|
||||
['DB_CONNECTION', true, $dbConnection],
|
||||
['pdo_mysql', $pdoMysqlLoaded, $pdoMysqlLoaded ? 'geladen' : 'nicht geladen'],
|
||||
['pdo_sqlsrv', $pdoSqlsrvLoaded, $pdoSqlsrvLoaded ? 'geladen' : 'nicht geladen'],
|
||||
['Erforderliche PDO-Erweiterung', extension_loaded($requiredExtension), $requiredExtension],
|
||||
['SaaS-App', is_dir(scripts_saas_app_path()), scripts_saas_app_path()],
|
||||
['.env.example', is_file(scripts_env_example_path()), scripts_env_example_path()],
|
||||
['.env', is_file(scripts_env_path()), is_file(scripts_env_path()) ? 'vorhanden' : 'noch nicht angelegt'],
|
||||
@@ -32,5 +39,6 @@ scripts_stdout('');
|
||||
scripts_stdout('Naechste Schritte:');
|
||||
scripts_stdout('1. Falls Composer fehlt, zuerst Composer installieren.');
|
||||
scripts_stdout('2. Mit `php scripts/prepare-saas-env.php` eine lokale .env anlegen.');
|
||||
scripts_stdout('3. Mit `php scripts/install-saas.php` das SQL-Bundle erzeugen.');
|
||||
scripts_stdout('4. Optional `php scripts/run-sql-migrations.php --server=... --database=...` fuer die direkte SQL-Ausfuehrung verwenden.');
|
||||
scripts_stdout('3. DB_CONNECTION in `saas-app/.env` auf mysql, mariadb oder sqlsrv pruefen.');
|
||||
scripts_stdout('4. Mit `php scripts/install-saas.php` das SQL-Bundle fuer den gewaehlten Treiber erzeugen.');
|
||||
scripts_stdout('5. Optional `php scripts/run-sql-migrations.php --connection=' . $dbConnection . ' --server=... --database=...` fuer die direkte SQL-Ausfuehrung verwenden.');
|
||||
|
||||
@@ -28,14 +28,16 @@ if ($prepareEnv) {
|
||||
}
|
||||
|
||||
try {
|
||||
$bundlePath = scripts_build_migration_bundle();
|
||||
$envValues = scripts_read_env_file(scripts_env_path());
|
||||
$dbConnection = scripts_normalize_db_connection($envValues['DB_CONNECTION'] ?? 'mysql');
|
||||
$bundlePath = scripts_build_migration_bundle(null, $dbConnection);
|
||||
} catch (Throwable $exception) {
|
||||
scripts_stderr($exception->getMessage());
|
||||
}
|
||||
|
||||
scripts_stdout('');
|
||||
scripts_stdout('SQL-Bundle erzeugt: ' . $bundlePath);
|
||||
scripts_stdout('SQL-Bundle fuer ' . scripts_connection_label($dbConnection) . ' erzeugt: ' . $bundlePath);
|
||||
scripts_stdout('Naechste Schritte:');
|
||||
scripts_stdout('1. saas-app/.env mit echten DB-, Mail- und Tenancy-Werten fuellen.');
|
||||
scripts_stdout('2. Das SQL-Bundle manuell importieren oder `php scripts/run-sql-migrations.php --server=... --database=...` verwenden.');
|
||||
scripts_stdout('2. Das SQL-Bundle manuell importieren oder `php scripts/run-sql-migrations.php --connection=' . $dbConnection . ' --server=... --database=...` verwenden.');
|
||||
scripts_stdout('3. Danach ersten Tenant, ersten Benutzer und erste Member-Zuordnung anlegen.');
|
||||
|
||||
@@ -6,18 +6,20 @@ require_once __DIR__ . '/support.php';
|
||||
|
||||
$options = scripts_parse_options($argv);
|
||||
$env = scripts_read_env_file(scripts_env_path());
|
||||
$connection = scripts_normalize_db_connection($options['connection'] ?? $env['DB_CONNECTION'] ?? 'mysql');
|
||||
|
||||
$config = [
|
||||
'connection' => $connection,
|
||||
'server' => $options['server'] ?? $env['DB_HOST'] ?? null,
|
||||
'database' => $options['database'] ?? $env['DB_DATABASE'] ?? null,
|
||||
'port' => $options['port'] ?? $env['DB_PORT'] ?? '1433',
|
||||
'port' => $options['port'] ?? $env['DB_PORT'] ?? scripts_default_db_port($connection),
|
||||
'username' => $options['username'] ?? $env['DB_USERNAME'] ?? null,
|
||||
'password' => $options['password'] ?? $env['DB_PASSWORD'] ?? null,
|
||||
];
|
||||
|
||||
try {
|
||||
scripts_run_sql_migrations($config);
|
||||
scripts_stdout('Migrationen wurden erfolgreich ausgefuehrt.');
|
||||
scripts_stdout('Migrationen fuer ' . scripts_connection_label($connection) . ' wurden erfolgreich ausgefuehrt.');
|
||||
} catch (Throwable $exception) {
|
||||
scripts_stderr('Migration fehlgeschlagen: ' . $exception->getMessage());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user