Meine wp_options mit den Autostarts lief über. War schon auf über 1 MB angewachsen, was schlecht für die Ladezeiten ist. Es gibt keine Tools, die die Options wirklich aufräumen. Aus gutem Grund.
Inhalt
wp_options
Die wp_options-Tabelle ist ein zentraler Bestandteil jeder WordPress-Installation. Sie speichert Konfigurationen, Einstellungen und temporäre Daten – sowohl von WordPress selbst als auch von Plugins und Themes.
Doch genau hier liegt das Problem: Mit der Zeit sammeln sich unzählige Einträge an, die oft nicht mehr benötigt werden. Besonders kritisch wird es, wenn diese Einträge als „autoload“ markiert sind. Dann werden sie bei jedem Seitenaufruf geladen – selbst wenn sie längst überflüssig sind.
Das Ergebnis? Deine Website wird langsamer, die Datenbank wächst unnötig an, und du verlierst den Überblick. Viele Plugins hinterlassen ihre Spuren in der wp_options, auch wenn sie längst deaktiviert oder deinstalliert wurden.
Ich wollte also ein Plugin haben, das mir die wp_options aufräumt. Das gibt es aber eben nicht. Den Schuh zieht sich niemand an, es nämlich wäre eine Irrsinnsarbeit, das Plugin zu pflegen.
wp_options
Man müsste schauen, welche Plugins installiert sind und was alles in der wp_options steht. Dann müsste man prüfen, welche installierten Plugins denn in der Options vorkommen. Unter den verschiedensten Bezeichnungen, denn glaubt mal nicht, dass die Entwickler immer dasselbe Prefix benutzen würden. Nö, das wäre ja einfach.
Dann tummeln sich in der wp_options auch noch ne Menge System-Autostarts, die man nicht löschen sollte. Nicht zu vergessen, dass auch Themes dort Daten speichern. Und dann gibt es auch noch SDKs für die Pro-Versionen, die von vielen Entwicklerm genutzt werden.
Tagtäglich kommen neue Plugins und neue Tabelleneinträge auf den Markt. Wer soll da noch die Übersicht behalten? Das kann niemand, nicht mal eine KI.
Die Übersicht behalten
Aber so eine künstliche Intelligenz kommt nahe ran. Das reicht mir. Ob es Dir reicht, musst Du wissen, die Benutzung des Plugins ist auf eigene Gefahr, auch wenn ein Backup erstellt wird.
Ich warf also Gemini an und schilderte ihm mein Vorhaben. Das nennt man Vibe Coding. Das ist am Ende umständlicher und langwieriger, als es sich anhören mag. Die Version 39 spricht ja Bände, oder?
Wie funktioniert das Plugin?
Das Plugin analysiert Deine wp_options-Tabelle und identifiziert potenziellen Datenmüll. Es geht dabei in mehreren Schritten vor:
1. Erkennung aktiver Plugins und Themes
Das Plugin ermittelt, welche Plugins und Themes aktuell aktiv sind. Nur Einträge, die zu diesen aktiven Komponenten gehören, werden als „sicher“ eingestuft.
2. Heuristische Analyse
Jeder Eintrag in der wp_options wird daraufhin überprüft, ob er zu einem aktiven Plugin, Theme oder einem bekannten Core-Präfix gehört. Falls nicht, wird er als potenzieller Löschkandidat markiert.
3. Ausgabe der Löschkandidaten
Es erscheint eine Liste mit möglichen Löschkandidaten (grün) und benötigten Einträgen (gelb).
4. Ausgabe eines KI Prompts
Es wird eine umfangreiche und (hoffentlich) sehr eindeutige Textausgabe generiert, die eine KI anweist, SQL-Befehle zu erstellen, die die wp_options aufräumen.
Prüfe die Liste der Löschkandidaten und passe den Ausgabeprompt des Plugins ggf. an. Entferne Einträge, bei denen Du Dir nicht sicher bist, ob sie gelöscht werden können.
5. Übergabe an eine KI
Du wählst nun die KI Deines geringsten Misstrauens aus und fügst den vom Plugin generierten Anweisungstext als Prompt ein. Die Ausgabe sollte dann eindeutig sein und Dir drei SQL-Befehle generieren:
- Backup nur der zu löschenden Einträge erstellen
- Einträge löschen
- Einen Wiederherstellungsbefehl, falls danach auf der Seite etwas nicht stimmen sollte.
6. Befehle ausführen
Nun musst Du Deinen phpMyAdmin öffnen und die ersten beiden Befehle dort ausführen.
Sicherheit
Die Ergebnisse werden in einer übersichtlichen Tabelle dargestellt. Aktive Einträge werden gelb, potenzieller Datenmüll grün hinterlegt. So behältst du die Kontrolle und kannst selbst entscheiden, was gelöscht werden soll.
KI-gestützte Validierung: Das Plugin generiert einen Textblock, den du an eine KI deiner Wahl senden kannst. Diese erstellt dann einen sicheren SQL-Löschplan – inklusive Backup und Wiederherstellungsmöglichkeit.
Das Plugin ist so konzipiert, dass es **keine kritischen WordPress-Core-Optionen** löscht. Stattdessen werden diese Einträge von vornherein ausgeblendet, um maximale Sicherheit zu gewährleisten. Dennoch: **Ein Backup deiner Datenbank ist Pflicht!** Das Plugin erinnert dich explizit daran, bevor du Änderungen vornimmst.
Verantwortung
Prüfe die Liste der Löschkandidaten und passe den Ausgabeprompt des Plugins ggf. an. Entferne Einträge, bei denen Du Dir nicht sicher bist, ob sie gelöscht werden können.
Zielgruppe und Disclaimer
– **WordPress-Administratoren**, die ihre Datenbank bereinigen und die Ladezeiten ihrer Website optimieren möchten.
– **Entwickler**, die ein Werkzeug suchen, um unnötige Einträge in der wp_options zu identifizieren und zu entfernen.
– **Technisch versierte Nutzer**, die bereit sind, die Ergebnisse manuell zu überprüfen und die Verantwortung für die Änderungen zu übernehmen.
Kein Plugin kann zu 1100 %garantieren, dass alle identifizierten Einträge tatsächlich überflüssig sind. Besonders bei Plugins, die ihre Präfixe nicht konsistent verwenden, kann es zu Fehleinschätzungen kommen. Daher ist es wichtig, dass du die Ergebnisse sorgfältig prüfst und im Zweifel auf die Löschung verzichtest.
Das **Autoload Options Cleaner V39** ist ein mächtiges Werkzeug, um deine WordPress-Datenbank von unnötigem Ballast zu befreien. Es bietet eine klare Übersicht, eine heuristische Analyse und eine KI-gestützte Validierung – alles, um dir die Entscheidung zu erleichtern. Aber denk daran: **Die Verantwortung liegt bei dir.** Nutze das Plugin mit Bedacht, führe Backups durch und überprüfe die Ergebnisse sorgfältig.
Das Plugin Autoload Options Cleaner
Als autoload-cleaner/autoload-cleaner.php in Deinem Plugin-Verzeichnis abspeichern und aktivieren.
<?php
/**
* Plugin Name: Autoload Options Cleaner "V39"
* Description: Entfernt starre Plugin-Präfixe aus der Heuristik und behält den Hard-Code-Ausschluss für kritische Core-Optionen (user_roles) bei. Benutzung auf eigene Gefahr.
* Version: 39.0
* Author: KI-Assistent
* License: GPL2
*/
// Sicherheitscheck: Direkten Zugriff verhindern
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Holt alle aktiven Plugin-Präfixe ab (Aggressive Generische Logik)
* @return array
*/
function autoload_cleaner_get_active_prefixes() {
$active_plugins = get_plugins();
$prefixes = array();
// 1. Core/Standard Präfixe HINZUFÜGEN (Nur generische WP-Präfixe)
$prefixes[] = 'theme_mods_';
$prefixes[] = 'widget_';
$prefixes[] = '_transient_';
$prefixes[] = '_site_transient_';
$prefixes[] = 'cron';
$prefixes[] = '_wp_session_';
$prefixes[] = '_site_cron';
// 2. Präfixe aus AKTIVEN Plugin-Namen ableiten (DYNAMISCH)
foreach ($active_plugins as $plugin_file => $plugin_data) {
$folder_name = dirname($plugin_file);
// A) Vollständiger Ordnername als Präfix
$clean_folder_name = str_replace(array('-', '/', ' '), '_', $folder_name);
$prefixes[] = strtolower($clean_folder_name) . '_';
// B) Alle Hauptteile des Ordnernamens als separate Präfixe
$parts = preg_split('/[_-]/', $folder_name, -1, PREG_SPLIT_NO_EMPTY);
foreach ($parts as $part) {
if (strlen($part) > 3) {
$prefixes[] = strtolower($part) . '_';
}
}
// C) Bereinigter Plugin-Titel als Präfix
$clean_title = sanitize_title($plugin_data['Name']);
$clean_title = str_replace('-', '_', $clean_title);
// Vermeidet doppelte Endungen
if (substr($clean_title, -1) !== '_') {
$prefixes[] = strtolower($clean_title) . '_';
} else {
$prefixes[] = strtolower($clean_title);
}
}
$prefixes = array_unique($prefixes);
// Entfernt generisches Rauschen
$prefixes = array_diff($prefixes, ['wp_', 'pro_', 'the_', 'for_', 'and_', 'settings_']);
// Längere Präfixe zuerst, um genauere Treffer zu gewährleisten
usort($prefixes, function($a, $b) {
return strlen($b) - strlen($a);
});
return $prefixes;
}
/**
* Versucht, eine Option einem aktiven Plugin oder Theme zuzuordnen (Reine Heuristik)
* @param string $option_name
* @return array|false
*/
function autoload_cleaner_identify_plugin($option_name) {
global $wpdb;
static $prefixes_map = null;
$db_prefix = $wpdb->prefix;
// Hard-Code Schutz für Benutzerrollen (Behalten als Fallback für die Identifikation)
if (strpos($option_name, 'user_roles') !== false && strlen($option_name) < (strlen($db_prefix) + 15)) {
return ['status' => 'active', 'name' => 'CORE: KRITISCHE BENUTZERROLLEN-OPTION (UNKRITISCH)', 'prefix' => 'CORE'];
}
if ($prefixes_map === null) {
$active_plugins = get_plugins();
$prefixes_map = [];
// 1. Theme-spezifische Präfixe HINZUFÜGEN (Zwingend schützen)
$stylesheet_name = get_stylesheet();
$template_name = get_template();
// Theme Mods (Customizer/Widget) Präfixe
$prefixes_map['theme_mods_' . $stylesheet_name] = 'Core/Theme Settings (Aktiv)';
$prefixes_map['theme_mods_' . $template_name] = 'Core/Theme Settings (Aktiv)';
// Direkte Theme Options-Tabelle (Oft der Theme-Name als Präfix)
$clean_stylesheet = str_replace(array('-', '/', ' '), '_', $stylesheet_name);
$prefixes_map[strtolower($clean_stylesheet) . '_'] = 'Aktives Theme Options';
$clean_template = str_replace(array('-', '/', ' '), '_', $template_name);
$prefixes_map[strtolower($clean_template) . '_'] = 'Aktives Theme (Eltern) Options';
// 2. Plugin-Präfixe aus aktiven Plugin-Namen ableiten
foreach ($active_plugins as $plugin_file => $plugin_data) {
$folder_name = dirname($plugin_file);
$plugin_name = $plugin_data['Name'];
$plugin_prefixes = [];
$clean_folder_name = str_replace(array('-', '/', ' '), '_', $folder_name);
$plugin_prefixes[] = strtolower($clean_folder_name) . '_';
$parts = preg_split('/[_-]/', $folder_name, -1, PREG_SPLIT_NO_EMPTY);
foreach ($parts as $part) {
if (strlen($part) > 3) {
$plugin_prefixes[] = strtolower($part) . '_';
}
}
$clean_title = sanitize_title($plugin_data['Name']);
$clean_title = str_replace('-', '_', $clean_title);
if (substr($clean_title, -1) !== '_') {
$plugin_prefixes[] = strtolower($clean_title) . '_';
} else {
$plugin_prefixes[] = strtolower($clean_title);
}
// Spezifische Plugin-Präfixe (cmplz_) wurden aus diesem Block entfernt.
foreach (array_unique($plugin_prefixes) as $prefix) {
$prefixes_map[$prefix] = $plugin_name;
}
}
}
// 3. Core/Standard-Präfixe zuerst prüfen (widget_, _transient_, theme_mods_ etc.)
$core_prefixes = [
'theme_mods_' => 'Core/Theme Settings',
'widget_' => 'Core/Widget Settings',
'_transient_' => 'Core/Temporary Cache',
'_site_transient_' => 'Core/Temporary Cache',
'cron' => 'Core/Scheduled Tasks',
'_wp_session_' => 'Core/Session Data',
'wp_ulike_' => 'WP ULike (Generischer Prefix)', // Kann bleiben
'wpp_' => 'WordPress Popular Posts (WPP) (Generischer Prefix)', // Kann bleiben
'fs_' => 'Freemius SDK (Generisch)' // Kann bleiben, da SDK oft universell ist
];
foreach ($core_prefixes as $prefix => $name) {
if (strpos($option_name, $prefix) === 0) {
return ['status' => 'active', 'name' => $name, 'prefix' => $prefix];
}
}
// 4. Prüfe die Optionen gegen die erstellte Zuordnungstabelle
foreach ($prefixes_map as $prefix => $plugin_name) {
if (strpos($option_name, $prefix) === 0) {
return ['status' => 'active', 'name' => $plugin_name, 'prefix' => $prefix];
}
}
// Wenn nichts gefunden wird, ist es Datenmüll
return ['status' => 'inactive', 'name' => 'DEAKTIVIERTES PLUGIN/THEME (Datenmüll)'];
}
/**
* Fügt das Plugin-Menü hinzu.
*/
function autoload_cleaner_menu() {
add_management_page(
'Autoload Cleaner',
'Autoload Cleaner',
'manage_options',
'autoload-cleaner',
'autoload_cleaner_page_content'
);
}
add_action( 'admin_menu', 'autoload_cleaner_menu' );
/**
* Erzeugt den Inhalt der Admin-Seite.
*/
function autoload_cleaner_page_content() {
global $wpdb;
$db_prefix = $wpdb->prefix;
$options_table_name = $db_prefix . 'options';
// *** KRITISCH: Liste der Core-Optionen, die NICHT angezeigt werden sollen ***
$core_options_to_hide = [
'user_roles',
'siteurl',
'home',
'blogname',
'blogdescription',
'admin_email',
'start_of_week',
'timezone_string',
'gmt_offset',
'default_role',
'WPLANG',
'upload_path',
'uploads_use_yearmonth_folders',
'mailserver_url',
'mailserver_login',
'mailserver_pass',
'mailserver_port',
'mailserver_auth',
'permalink_structure',
'category_base',
'tag_base'
];
// ************************************************************************
$limit = 500;
$min_size = 50;
$sql = $wpdb->prepare(
"SELECT option_id, option_name, LENGTH(option_value) as option_size
FROM {$options_table_name}
WHERE autoload = 'yes' AND LENGTH(option_value) >= %d
ORDER BY option_size DESC
LIMIT %d",
$min_size, $limit
);
$results = $wpdb->get_results( $sql );
$total_autoload_size = $wpdb->get_var( "SELECT SUM(LENGTH(option_value)) FROM {$options_table_name} WHERE autoload = 'yes'" );
$active_plugins_list = [];
$active_plugins_bullet_list = [];
$active_plugins = get_plugins();
foreach ($active_plugins as $plugin_file => $plugin_data) {
$active_plugins_list[] = $plugin_data['Name'];
$active_plugins_bullet_list[] = '* ' . $plugin_data['Name'];
}
$active_theme_name = wp_get_theme()->get('Name');
$active_plugins_bullet_list[] = '* AKTIVES THEME: ' . $active_theme_name;
$delete_candidates_list = [];
echo '<div class="wrap"><h1>Autoload Options Cleaner "V39" </h1>';
echo '<p>Ihr Datenbank-Präfix ist: <strong>' . esc_html($db_prefix) . '</strong></p>';
echo '<p>Gesamtgröße aller automatisch geladenen Optionen: <strong>' . size_format( $total_autoload_size, 2 ) . '</strong></p>';
echo '<p><strong>ACHTUNG: Führen Sie VOR einer Löschung UNBEDINGT ein aktuelles Datenbank-Backup durch! Benutzung auf EIGENE GEFAHR!</strong></p>';
if ( ! $results ) {
echo '<p>Keine automatisch geladenen Optionen (über 50 Bytes) gefunden.</p></div>';
return;
}
// Tabelle zur visuellen Überprüfung
echo '<h2>1. Visuelle Überprüfung der ' . count($results) . ' größten Autoload-Einträge (mind. 50 Bytes)</h2>';
echo '<p>Die farbliche Kennzeichnung (Grün = potenzieller Müll) erfolgt nur heuristisch. **WP-Core-Optionen werden ausgeblendet, um maximale Sicherheit zu gewährleisten.**</p>';
echo '<table class="wp-list-table widefat fixed striped">';
echo '<thead><tr><th>Option Name</th><th>Größe</th><th>Zuordnung</th></tr></thead>';
echo '<tbody>';
foreach ( $results as $result ) {
// --- HARTER AUSSCHLUSS FÜR CORE-OPTIONEN (user_roles etc.) ---
// Entfernt den Präfix, um den Abgleich durchzuführen.
$option_core_name = str_replace($db_prefix, '', $result->option_name);
if ( in_array($option_core_name, $core_options_to_hide, true) ) {
continue; // Option wird übersprungen und nicht angezeigt
}
// --------------------------------------------------------
$identification = autoload_cleaner_identify_plugin($result->option_name);
$status_data = $identification;
$class = '';
$hint = '';
if ($status_data['status'] === 'inactive') {
// GRÜN: Löschkandidat
$class = 'style="background-color: #d4edda; color: #155724;"';
$hint = 'GEFAHRLOS: Gehört wahrscheinlich zu einem ' . esc_html($status_data['name']) . '.';
$delete_candidates_list[] = [
'name' => $result->option_name,
'size' => size_format($result->option_size, 2),
'option_id' => $result->option_id
];
} else {
// GELB: Aktiv oder Core-Plugin/Theme
$class = 'style="background-color: #fff3cd; color: #856404;"';
$hint = 'Aktiv: ' . esc_html($status_data['name']);
}
echo '<tr ' . $class . '>';
echo '<td><strong>' . esc_html( $result->option_name ) . '</strong></td>';
echo '<td>' . size_format( $result->option_size, 2 ) . '</td>';
echo '<td>' . esc_html( $hint ) . '</td>';
echo '</tr>';
}
echo '</tbody></table>';
// --- KI/MANUELLER ANALYSE BLOCK ---
echo '<div style="margin-top: 30px; border: 1px solid #c3c4c7; padding: 20px; background-color: #f7f7f7;">';
echo '<h2>2. KI-Analyse-Basis (Zur Copy & Paste Nutzung)</h2>';
echo '<p>Kopieren Sie den folgenden Textblock komplett und fügen Sie ihn in eine Nachricht an die KI ein. Die KI **muss** den sicheren SQL-Löschplan erstellen.</p>';
// --- Der reine Textblock für die KI-Kommunikation beginnt hier ---
$analysis_text = "Bitte vergleiche die Liste der Autoload-Einträge (Löschkandidaten) mit den installierten Plugins und dem aktiven Theme und erstelle einen endgültigen, sicheren Löschplan (SQL-Befehle).
**KRITISCHE ANWEISUNGEN FÜR DIE KI (HALLUZINATIONSVERBOT & PRÄFIX-KORREKTUR):**
1. **DATENBANK-PRÄFIX ZWINGEND ANWENDEN:** Der Präfix '{$db_prefix}' MUSS in allen SQL-Befehlen anstelle des Standard-Präfixes 'wp_' verwendet werden. Die Tabelle heißt `{$db_prefix}options`.
2. **LÖSCHLOGIK ZWINGEND ANWENDEN:** Nur die Einträge in Liste 2 sind aktiv. Alle Optionen, die Präfixe von **inaktiven** Plugins oder **inaktiven** Themes tragen, **MÜSSEN** als Reste (Datenmüll) betrachtet und zum Löschen vorgeschlagen werden. Optionen, die zu dem in Liste 2 genannten AKTIVEN THEME gehören, DÜRFEN NICHT gelöscht werden.
3. **CORE-OPTIONEN AUSGESCHLOSSEN:** Die angezeigten Einträge enthalten keine bekannten WordPress-Core-Optionen (wie *user_roles*).
**SQL-FORMATIERUNG (AUSGABE MUSS SEPARAT ERFOLGEN):**
Der resultierende Löschplan MUSS DREI SQL-Befehle enthalten, die jeweils in einem SEPARATEN SQL-CODE-BLOCK ausgegeben werden:
A. **SICHERUNG (BACKUP):** Ein Befehl, der eine zeitgestempelte Backuptabelle (z.B. {$db_prefix}options_backup_autoload_YYYYMMDD_HHMMSS) der zu löschenden Optionen erstellt.
B. **LÖSCHEN (DELETE):** Der DELETE-Befehl.
C. **WIEDERHERSTELLUNG (UNDO/RECOVERY):** Der vollständige SQL-Befehl zur Wiederherstellung der gesicherten Einträge aus der Backuptabelle. **KRITISCH:** Verwende ZWINGEND **INSERT IGNORE INTO** (nicht nur INSERT INTO), um den Fehler **#1062 (Doppelter Eintrag)** zu verhindern. Die SQL-Zeile MUSS mit **INSERT IGNORE INTO** beginnen.
### 1. DATENBANK-PRÄFIX (FÜR ALLE TABELLENNAMEN ZU VERWENDEN)
{$db_prefix}
### 2. AKTUELL INSTALLIERTE PLUGINS & AKTIVES THEME (NUR DIESE SIND AKTIV)
" . implode("\n", $active_plugins_bullet_list) . "
### 3. AUTOLOAD-OPTIONEN (BESTÄTIGTE RÜCKSTÄNDE ZUR LÖSCHUNG)
";
if (!empty($delete_candidates_list)) {
foreach ($delete_candidates_list as $item) {
$analysis_text .= $item['name'] . ' (' . $item['size'] . ', ID: ' . $item['option_id'] . ')' . "\n";
}
} else {
$analysis_text .= "Keine Löschkandidaten gefunden.";
}
// Jetzt die tatsächliche Textarea mit den gesammelten Daten anzeigen
$row_count = count($delete_candidates_list) + count($active_plugins_list) + 28;
echo '<textarea rows="' . $row_count . '" cols="100" onclick="this.select();" readonly style="width: 100%; min-height: 400px; font-family: monospace; font-size: 14px; background-color: #fff; border: 1px solid #ccc;">' . esc_textarea($analysis_text) . '</textarea>';
echo '</div>'; // End KI Block
echo '</div>'; // End wrap
}
?>



