Wien man ausnehmen custom tables in TYPO3 Database Analyser

Beim Arbeiten mit TYPO3 können Sie externe oder benutzerdefinierte Tabellen haben, die Sie nicht möchten, dass der Datenbankanalysator von TYPO3 verarbeitet. Dies ist üblich, wenn WordPress-Tabellen (wp_ Präfix) oder andere Integrationen von Drittanbietern verwendet werden.

Einführung in den TYPO3 Database Analyser

In einigen TYPO3-Projekten können benutzerdefinierte Tabellen vorhanden sein, die Sie nicht möchten, dass der Datenbankanalysator von TYPO3 (Install Tool → "Datenbankstruktur analysieren") ändert oder löscht. Dies ist üblich, wenn Sie Tabellen von Drittanbietern haben (z. B. WordPress-Tabellen wie wp_*) oder externe Daten, die von den Schema-Verwaltungsprozessen von TYPO3 unberührt bleiben müssen.

In diesem Tutorial werden wir zwei Ansätze erkunden, um benutzerdefinierte Tabellen im Datenbankanalysator zu ignorieren:

  • Verwendung eines Ereignislisteners (AlterTableDefinitionStatementsEvent)
  • Überschreiben des ConnectionMigrator und Verwendung von IGNORE_TABLE_PREFIXES/IGNORE_TABLE_NAMES

Beide Methoden funktionieren in TYPO3 v12 und TYPO3 v13 und können mit minimalen Änderungen an frühere Versionen angepasst werden.

Ansatz 1: Verwendung eines Ereignislisteners

In diesem Verfahren hängen wir uns in den Datenbankschemagenerierungsprozess ein, indem wir das Ereignissystem von TYPO3 verwenden. Wir werden TYPO3 anweisen, bestimmte Tabellen (z. B. diejenigen mit dem Präfix wp_) zu erkennen, damit es sie nicht als "zum Löschen" markiert.

Schritt 1: Ereignis in Services.yaml registrieren Erstellen oder aktualisieren Sie Ihre Services.yaml (normalerweise im Konfigurationsordner Ihrer Erweiterung zu finden), um einen Listener für das AlterTableDefinitionStatementsEvent zu registrieren.

# Configuration/Services.yaml
services:
  Vendor\MyExtension\EventListener\Setup:
    tags:
      - name: event.listener
        identifier: 'table-connection'
        method: 'schemaEvent'
        event: TYPO3\CMS\Core\Database\Event\AlterTableDefinitionStatementsEvent

Schritt 2: Erstellen Sie die Event Listener PHP-KlasseUnten finden Sie eine Beispielsklasse in PHP, die Ihre benutzerdefinierten Tabellen zur internen Schemaliste von TYPO3 hinzufügt und TYPO3s Datenbankanalysator effektiv mitteilt, dass sie Teil des gültigen Schemas sind (und daher nicht gelöscht werden sollten).

<?php
namespace Vendor\MyExtension\EventListener;

use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Database\Event\AlterTableDefinitionStatementsEvent;

class Setup
{
    /**
     * Builds and returns the current schema for the Install Tool.
     *
     * @param array $list List of SQL statements
     * @return array SQL statements required for the install tool
     */
    public function Schema(array $list): array
    {
        $connectionPool = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class);
        $connection = $connectionPool->getConnectionByName('Default');
        $schemaManager = $connection->createSchemaManager();
        
        $tables = [];
        // Fetch custom tables starting with 'wp_'
        foreach ($schemaManager->listTableNames() as $tableName) {
            if (!\str_starts_with($tableName, 'wp_')) {
                continue;
            }
            $tables[] = $tableName;
        }
        
        // For each custom table, retrieve and modify the CREATE statement
        foreach ($tables as $wpTable) {
            $query = "SHOW CREATE TABLE `$wpTable`";
            $result = $connection->query($query);
            $row = $result->fetch();

            $createTableQuery = $row['Create Table'] ?? '';
            // Minor string modifications to make it compatible
            $createTableQuery = str_replace('"', '`', $createTableQuery);
            $createTableQuery = preg_replace('/CONSTRAINT `[a-zA-Z0-9_-]+` /', '', $createTableQuery);
            $createTableQuery = preg_replace('/ DEFAULT CHARSET=[^ ;]+/', '', $createTableQuery);
            $createTableQuery = preg_replace('/ COLLATE=[^ ;]+/', '', $createTableQuery);

            $list[] = $createTableQuery . ";\n";
        }

        return ['sqlString' => $list];
    }
    
    /**
     * Handle the AlterTableDefinitionStatementsEvent to prevent dropping certain tables.
     */
    public function schemaEvent(AlterTableDefinitionStatementsEvent $event): void
    {
        $list = $this->Schema([]);
        foreach ($list['sqlString'] ?? [] as $sql) {
            $event->addSqlData($sql);
        }
    }
}

Lassen Sie uns sehen, wie es funktioniert

  • Wenn der Datenbankanalysator von TYPO3 läuft, löst er - AlterTableDefinitionStatementsEvent aus.
  • Unser Listener greift auf die wp_ Tabellen in der Datenbank zu, ruft ihre CREATE-Anweisungen ab und fügt sie dem erkannten Schema hinzu.
  • Der Datenbankanalysator sieht diese Tabellen nun als gültig an und listet sie nicht zur Löschung auf.

Ansatz 2: Überschreiben des ConnectionMigrator

Wenn Sie einen direkteren Ansatz bevorzugen - insbesondere wenn Sie häufig große Tabellensätze ignorieren müssen - könnte das Überschreiben der ConnectionMigrator-Klasse einfacher sein. Der Datenbankvergleich von TYPO3 ermöglicht es Ihnen, Präfixe und Tabellennamen vollständig zu ignorieren.

Schritt 1: Konfigurieren Sie ext_localconf.php oder AdditionalConfiguration.php Fügen Sie die folgenden Zeilen hinzu, um TYPO3 mitzuteilen, welche Tabellenpräfixe und spezifischen Tabellennamen ignoriert werden sollen:

// Ignore tables with a specific prefix
$GLOBALS['TYPO3_CONF_VARS']['SYS']['DATABASE_COMPARE']['IGNORE_TABLE_PREFIXES'] = [
    'wp_',
];

// Ignore specific table names
$GLOBALS['TYPO3_CONF_VARS']['SYS']['DATABASE_COMPARE']['IGNORE_TABLE_NAMES'] = [
    'some_table_name',
];

Schritt 2: Überschreiben von ConnectionMigratorAls nächstes überschreiben Sie den ConnectionMigrator-Dienst in ext_localconf.php (oder in der Konfiguration Ihrer Erweiterung). Dadurch wird TYPO3 gezwungen, Ihre benutzerdefinierte Klasse anstelle des Standardkerns zu verwenden:

// Override the default ConnectionMigrator
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][\TYPO3\CMS\Core\Database\Schema\ConnectionMigrator::class] = [
    'className' => \Vendor\ExtensionName\Database\Schema\ConnectionMigrator::class
];

Schritt 3: Erstellen Sie Ihre benutzerdefinierte ConnectionMigrator-KlasseIn Ihrer Erweiterung unter Klassen/Datenbank/Schema/ConnectionMigrator.php:

<?php
declare(strict_types=1);

namespace Vendor\ExtensionName\Database\Schema;

use Doctrine\DBAL\Schema\SchemaDiff;
use Doctrine\DBAL\Schema\Table;

class ConnectionMigrator extends \TYPO3\CMS\Core\Database\Schema\ConnectionMigrator
{
    protected function buildSchemaDiff(bool $renameUnused = true): SchemaDiff
    {
        $schemaDiff = parent::buildSchemaDiff($renameUnused);
        return $this->cleanSchemaDiff($schemaDiff);
    }

    protected function cleanSchemaDiff(SchemaDiff $schemaDiff): SchemaDiff
    {
        $schemaDiff->newTables     = $this->cleanTables($schemaDiff->newTables);
        $schemaDiff->changedTables = $this->cleanTables($schemaDiff->changedTables);
        $schemaDiff->removedTables = $this->cleanTables($schemaDiff->removedTables);
        
        return $schemaDiff;
    }

    protected function cleanTables(array $tables): array
    {
        $ignorePrefixes = $GLOBALS['TYPO3_CONF_VARS']['SYS']['DATABASE_COMPARE']['IGNORE_TABLE_PREFIXES'] ?? [];
        $ignoreTables   = $GLOBALS['TYPO3_CONF_VARS']['SYS']['DATABASE_COMPARE']['IGNORE_TABLE_NAMES'] ?? [];
        $deletedPrefix  = $this->deletedPrefix;

        return array_filter(
            $tables,
            function ($table) use ($ignorePrefixes, $ignoreTables, $deletedPrefix) {
                if ($table instanceof Table) {
                    $tableName = $table->getName();
                } else {
                    // For changed/removed tables, newName or name might be used
                    $tableName = trim($table->newName ?: $table->name, '`');
                }

                // If the table name has a deleted prefix, remove that before comparing
                if (strpos($tableName, $deletedPrefix) === 0) {
                    $tableName = substr($tableName, strlen($deletedPrefix));
                }

                // Ignore if table is explicitly listed or has an ignored prefix
                if (in_array($tableName, $ignoreTables, true)) {
                    return false;
                }

                foreach ($ignorePrefixes as $prefix) {
                    if (strpos($tableName, $prefix) === 0) {
                        return false;
                    }
                }

                return true;
            }
        );
    }
}

Lassen Sie uns sehen, wie es funktioniert

  • Dieser benutzerdefinierte Migrator überprüft alle neuen, geänderten und entfernten Tabellen während der Schemaanalyse.
  • Er filtert alle Tabellen heraus, deren Name einem Präfix in IGNORE_TABLE_PREFIXES oder einem Namen in IGNORE_TABLE_NAMES entspricht.
  • Als Ergebnis werden diese Tabellen nicht im Database Compare-Tool von TYPO3 für die Erstellung oder das Löschen aufgelistet.

Wie man in Real-World-Anwendungen verwendet

  • WordPress und TYPO3 Hybrid: TYPO3 neben WordPress in der gleichen Datenbank ausführen. Sie können alle wp_*-Tabellen ignorieren, damit TYPO3 nie versucht, sie zu berühren.
  • Drittanbieter-Integrationen: Bei der Verwendung externer Module (wie E-Commerce-Lösungen), die Daten in benutzerdefinierten Tabellen speichern, können Sie sicherstellen, dass diese Tabellen intakt bleiben.
  • Benutzerdefinierte Daten: Wenn Sie eigene nicht registrierte Tabellen haben (nicht von TYPO3 verwaltet), können Sie sie vor versehentlichen Änderungen schützen.

Abschluss

Das Ignorieren bestimmter Datenbanktabellen des TYPO3-Datenbankanalysators kann unerwartete Löschungen oder Änderungen an kritischen Daten verhindern. Sie können einen dieser beiden Ansätze wählen:

  • Event-Listener: Fügen Sie die benutzerdefinierten Tabellen dynamisch in das von TYPO3 erkannte Schema ein.
  • Überschreiben des ConnectionMigrators: Verwenden Sie die integrierten Ignorierlisten von TYPO3 für Präfixe und Namen.

Beide Methoden sind gültig und können an verschiedene Szenarien angepasst werden. Wenn Sie nur wenige spezielle Tabellen haben, bietet Ihnen der Ansatz des Event-Listeners eine feine Kontrolle. Wenn Sie ein konsistentes Muster von zu ignorierenden Tabellen haben (z. B. immer wp_ ignorieren), könnte die Überschreibung des ConnectionMigrators einfacher sein.

Wenn Ihnen dieses TYPO3-Tutorial geholfen hat, teilen Sie Ihren Lieblingsteil in den Kommentaren! Fühlen Sie sich frei, Strategien zu kombinieren oder auszuwählen, die am besten zu Ihrem Workflow passen.

Viel Spaß beim Coden in TYPO3!

Post a Comment

×

    Got answer to the question you were looking for?