Massensuche & Ersetzen in TYPO3-Seiten & tt_content durchführen

Hallo TYPO3-Enthusiasten! Wenn Sie jemals vor der Herausforderung standen, bestimmte Zeichenfolgen, URLs oder Texte auf einer großen Anzahl von TYPO3-Seiten ersetzen zu müssen, wissen Sie, dass dies eine ziemliche Aufgabe sein kann. In diesem Tutorial führen wir Sie durch ein benutzerdefiniertes PHP-Skript, das eine massive Suchen & Ersetzen-Operation in Ihrer TYPO3-Datenbank durchführt.

Warum benötigen Sie eine Massen-Suche und -Ersetzung?

  • Domain-Migration: Vielleicht sind Sie von example.com zu newdomain.com umgezogen und möchten alle Verweise aktualisieren.
  • Alte URLs reparieren: Möglicherweise haben Sie Ihre Seitenstruktur geändert oder defekte Links entdeckt.
  • Benutzerdefinierten Text oder Links ändern: Möglicherweise möchten Sie bestimmten Text oder Markennamen auf vielen Seiten ersetzen.

Anstatt 100+ Seiten manuell zu öffnen, kann Ihnen ein schnelles Skript Stunden (oder sogar Tage!) wiederholter Arbeit ersparen.

Wichtige Tipps vor dem Start

  • Sichern Sie Ihre Datenbank: Jede direkte Manipulation der Datenbank birgt Risiken. Erstellen Sie immer eine vollständige Sicherungskopie Ihrer Datenbank (z. B. über phpMyAdmin oder MySQL-Dump), bevor Sie Skripte ausführen, die Datensätze aktualisieren. 
  • Arbeiten Sie in einer Testumgebung: Führen Sie Ihr Skript zuerst in einer Entwicklungs-/Staging-Umgebung aus und testen Sie es. Wechseln Sie erst in die Produktion, wenn Sie sicher sind. 
  • Überprüfen Sie Tabellen-/Spaltennamen: Ihre TYPO3-Installation könnte leicht unterschiedliche Tabellen- oder Spaltennamen haben, wenn Sie sie angepasst haben. Überprüfen Sie alles doppelt.

Anleitung zur Massensuche und -ersetzung in TYPO3-Seiten & tt_content

1. Richten Sie Ihre Datenbankanmeldeinformationen ein

Sie müssen sich mit der gleichen Datenbank verbinden, die Ihre TYPO3-Installation verwendet. Diese Informationen finden Sie normalerweise in typo3conf/LocalConfiguration.php.

$host   = 'localhost';
$dbName = 'YOUR_DATABASE_NAME';
$dbUser = 'YOUR_DB_USER';
$dbPass = 'YOUR_DB_PASSWORD';

2. Erstellen Sie eine CSV-Datei mit Ersetzungen

Zur Bequemlichkeit erstellen Sie eine komma-separierte CSV-Datei mit drei Spalten:

  • Seiten-URL (Slug) – Diese wird verwendet, um die richtige Seite in der Seiten Tabelle zu finden.
  • Alter String/URL – Der Text, den Sie ersetzen möchten.
  • Neuer String/URL – Der neue Text, der den alten ersetzen wird.

Beispiel CSV (jede Zeile hat 3 Spalten):

https://t3planet.de/en/blog/learn-typo3-resources/,/en/customer/account,/en/enn3/
https://t3planet.de/blog/learn-typo3-resources/,/en/customer/account,/en/dee2/

Hinweis: Diese CSV-Datei kann überall gespeichert werden - auf Ihrem lokalen Rechner, Server usw. In unserem Tutorial verwenden wir einfach einen fest codierten String zur Vereinfachung, aber Sie können diesen Teil problemlos durch ein file_get_contents('/Pfad/zur/Ihrer-Datei.csv') ersetzen.

3. Verstehen Sie die Tabellenstruktur

In diesem Tutorial konzentrieren wir uns auf zwei Kern-TYPO3-Tabellen:

Seiten

  • Enthält Ihre Seiten-Datensätze.
  • Wir werden das Feld slug (oder uid, wenn Sie möchten) nachschlagen, um die richtige Seite zu finden.
  • Zusätzlich könnten wir nach sys_language_uid filtern, wenn Sie mit mehrsprachigen Websites arbeiten.

tt_content

  • Speichert die Inhaltslemente für jede Seite.
  • Typische Felder sind Überschrift, Bodytext, pi_flexform, usw.
  • Wir werden den Bodytext (und optional pi_flexform) aktualisieren, indem wir eine Suche & Ersetzen durchführen.
  • Die tt_content-Tabelle verweist über pid (oder page_id in einigen benutzerdefinierten Fällen) zurück auf Seiten.

4. Das PHP-Skript

Im Folgenden finden Sie das vollständige Skript. Stellen Sie sicher, dass Sie es an einem sicheren Ort platzieren, da jeder, der darauf zugreift, Änderungen in Ihrer Datenbank vornehmen könnte! Passen Sie die Anmeldeinformationen, Tabellennamen und CSV-Daten bei Bedarf an.

<?php
/**
 * Mass Find & Replace Script for TYPO3
 *
 * Requirements:
 * - pages table with fields: uid, slug, sys_language_uid
 * - tt_content table with fields: pid (matching pages.uid), bodytext, pi_flexform
 *
 * This script:
 * 1) Looks up the pages.uid based on the CSV's page slug and language.
 * 2) Runs REPLACE() on tt_content.bodytext & tt_content.pi_flexform
 *    for records matching pid = pages.uid (and a sys_language_uid if desired).
 */

$host   = 'localhost';
$dbName = 'YOUR_DATABASE_NAME';
$dbUser = 'YOUR_DB_USER';
$dbPass = 'YOUR_DB_PASSWORD';

try {
    // 1. Connect to database using PDO
    $pdo = new PDO(
        "mysql:host=$host;dbname=$dbName;charset=utf8",
        $dbUser,
        $dbPass,
        [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,  // Throw exceptions on errors
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]
    );
} catch (PDOException $e) {
    die("Database connection failed: " . $e->getMessage());
}

// 2. Load CSV data (example uses a hardcoded string)
$baseDomain = "https://t3planet.de";

// $csvData = file_get_contents('/path/to/your-file.csv');
$csvData = <<<CSV
https://t3planet.de/en/blog/learn-typo3-resources/,/en/learn-typo3,/en/new-learn-typo3
https://t3planet.de/blog/lernen-typo3-tessourcen/,/en/lernen-typo3,/en/new-lernen-typo3
CSV;

// 3. Parse CSV lines
$lines = explode("\n", trim($csvData));

foreach ($lines as $lineIndex => $line) {
    $columns = str_getcsv($line); // Split a CSV line into an array

    if (count($columns) !== 3) {
        echo "Line " . ($lineIndex + 1) . ": Invalid CSV format, skipping.<br>";
        continue;
    }

    list($pageUrl, $oldUrl, $newUrl) = $columns;

    // Remove domain from the pageUrl
    $pageUrl = str_replace($baseDomain, '', $pageUrl);

    // Determine sys_language_uid (example: /en/blog => sys_language_uid=0, otherwise 1)
    if (str_contains($pageUrl, '/en/blog')) {
        $pageUrl = str_replace("/en/blog", "", $pageUrl);
        $sys_language_uid = 0;
    } else {
        $pageUrl = str_replace("/blog", "", $pageUrl);
        $sys_language_uid = 1;
    }

    // Clean up trailing slashes & whitespace
    $pageUrl = rtrim($pageUrl, '/');
    $pageUrl = trim($pageUrl);
    $oldUrl  = trim($oldUrl);
    $newUrl  = trim($newUrl);

    // Basic sanity check
    if (empty($pageUrl) || empty($oldUrl) || empty($newUrl)) {
        echo "Line " . ($lineIndex + 1) . ": One or more columns are empty, skipping.<br>";
        continue;
    }

    // 4. Find the page UID based on slug & language
    try {
        $pageQuery = $pdo->prepare("
            SELECT uid
            FROM pages
            WHERE slug = :slug
              AND sys_language_uid = :sys_language_uid
        ");
        $pageQuery->bindValue(':slug',             $pageUrl,         PDO::PARAM_STR);
        $pageQuery->bindValue(':sys_language_uid', $sys_language_uid, PDO::PARAM_INT);
        $pageQuery->execute();
        $page = $pageQuery->fetch();

        if (!$page) {
            echo "NO PAGE FOUND: slug '{$pageUrl}' does not exist for sys_language_uid = {$sys_language_uid}.<br>";
            continue;
        }

        $pageId = (int)$page['uid'];

    } catch (Exception $e) {
        echo "ERROR retrieving page uid for slug '{$pageUrl}': " . $e->getMessage() . "<br>";
        continue;
    }

    // 5. Replace oldUrl with newUrl in tt_content for that page
    try {
        $stmt = $pdo->prepare("
            UPDATE tt_content
               SET bodytext = REPLACE(bodytext, :oldUrl, :newUrl),
                   pi_flexform = REPLACE(pi_flexform, :oldUrl, :newUrl)
             WHERE pid = :pid
               AND sys_language_uid = :sys_language_uid
        ");

        $stmt->bindValue(':oldUrl',           $oldUrl,          PDO::PARAM_STR);
        $stmt->bindValue(':newUrl',           $newUrl,          PDO::PARAM_STR);
        $stmt->bindValue(':pid',              $pageId,          PDO::PARAM_INT);
        $stmt->bindValue(':sys_language_uid', $sys_language_uid, PDO::PARAM_INT);

        $stmt->execute();
        $affectedRows = $stmt->rowCount();

        if ($affectedRows > 0) {
            echo "SUCCESS: Updated {$affectedRows} row(s) for Page UID: {$pageId}, Slug: {$pageUrl}<br>";
        } else {
            echo "NO CHANGE: No rows updated for Page UID: {$pageId}, Slug: {$pageUrl}<br>";
        }
    } catch (Exception $e) {
        echo "ERROR updating content for slug '{$pageUrl}': " . $e->getMessage() . "<br>";
    }
}

// Script completion message
echo "<br>--- Script Completed ---<br>";
?>

5. Gründlich testen!

  • Auf einer Testumgebung ausführen: Das Skript aktualisiert Datenbankeinträge, daher zuerst auf einer nicht produktiven Kopie testen.
  • Änderungen überprüfen: Schauen Sie sich einige Seiten Ihrer TYPO3-Website an, um sicherzustellen, dass der alte String korrekt ersetzt wurde.

Abschluss

Das war's! Sie haben jetzt ein leistungsstarkes Skript, um Massen-Find & Replace auf Ihrem TYPO3-Inhalt durchzuführen. Dies ist ein Lebensretter bei der Bewältigung von Änderungen im großen Maßstab - denken Sie immer daran, immer Sicherungskopien zu erstellen und gründlich zu testen. Wenn Sie dies hilfreich fanden, teilen Sie es gerne mit anderen TYPO3-Benutzern und tragen Sie Ihre Verbesserungen zur Community bei! Wenn Sie Fragen oder Anregungen haben, hinterlassen Sie einen Kommentar auf unserem T3Planet-Blog. Viel Spaß beim TYPO3-en!

Post a Comment

×

    Got answer to the question you were looking for?