Wiederholen Sie sich nicht: Automatisieren Sie sich wiederholende Aufgaben mit WP-CLI

Veröffentlicht: 2022-03-11

Haben Sie sich schon einmal dabei erwischt, in den WordPress-Adminbereich zu gehen, um Themen, Plugins und den WP-Kern zu aktualisieren? Natürlich hast du. Wurden Sie gefragt: „Können Sie alle Benutzer in dieser CSV-Datei erstellen/aktualisieren/löschen?“ Ich bin sicher, Sie sind auch darauf gestoßen. Haben Sie versucht, eine Website zu migrieren, und sich gewünscht, es gäbe ein Plugin oder ein Drittanbieter-Tool, auf das Sie zugreifen könnten, um die Arbeit zu erledigen? Ich weiß, ich habe!

Automatisierung sich wiederholender Aufgaben mit WP-CLI

Es gibt ein sehr leistungsfähiges Tool, das Ihnen bei diesen Aufgaben und mehr hilft. Bevor ich Ihnen davon erzähle, möchte ich eine kurze Anekdote erzählen.

Das Problem: In einem aktuellen Projekt gab es mehrere programmatische Aufgaben, die ich regelmäßig wiederholen musste. Eine Aufgabe bestand insbesondere darin, die Berechtigungen auf Benutzerebene basierend auf dem Nachweis des Kaufs oder Abonnements auf Mitgliedsebene zu aktualisieren. Wenn das Unternehmen keine Zahlung vom Benutzer für eine bestimmte Mitgliedschaftsstufe finden konnte, wollte es, dass die Mitgliedschaftsstufe vom Benutzer entfernt wurde. Warum war das nötig? Vielleicht hat ein Mitglied ein Abonnement beendet, aber ein Ereignis wurde nicht ausgelöst, sodass das Mitglied immer noch Zugriff hat, obwohl es nicht dafür bezahlt (Huch!). Oder vielleicht hatte jemand ein Testangebot, aber dieses Angebot ist abgelaufen und der Kunde hat noch ein Abonnement (ebenfalls huch!).

Die Lösung: Anstatt in das Admin-Panel zu gehen und Hunderte (vielleicht Tausende) von Abonnements manuell zu löschen, entschied ich mich für eines meiner Lieblings-WordPress-Tools, WP-CLI, das das Problem mit wenigen Tastenanschlägen behob.

In diesem Beitrag möchte ich Ihnen WP-CLI vorstellen (vorausgesetzt, Sie sind nicht bereits enge Freunde), Sie durch einen einfachen benutzerdefinierten Befehl führen, den ich für diese spezielle Situation geschrieben habe, und Ihnen einige Ideen und Ressourcen für die Verwendung von WP-CLI geben Ihre eigene Entwicklung.

Was ist WP-CLI?

Wenn Sie noch nie von WP-CLI gehört haben, sind Sie nicht allein. Obwohl das Projekt mehrere Jahre alt war, schien es für eine Weile unter dem WordPress-Radar zu fliegen. Hier ist eine kurze Beschreibung dessen, was WP-CLI ist und tut, von der offiziellen Website:

WP-CLI ist eine Reihe von Befehlszeilentools zur Verwaltung von WordPress-Installationen. Sie können Plugins aktualisieren, Multisite-Installationen einrichten und vieles mehr, ohne einen Webbrowser zu verwenden.

Die folgenden Befehle zeigen Ihnen die Leistungsfähigkeit von WP-CLI out of the box:

  • wp plugin update --all aktualisiert alle aktualisierbaren Plugins.
  • wp db export exportiert einen SQL-Dump deiner Datenbank.
  • wp media regenerate regeneriert Thumbnails für Anhänge (z. B. nachdem Sie die Größe in Ihrem Design geändert haben).
  • wp checksum core überprüft, ob WordPress-Kerndateien nicht manipuliert wurden.
  • wp search-replace sucht und ersetzt Strings in der Datenbank.

Wenn Sie hier weitere Befehle untersuchen, werden Sie feststellen, dass es viele verfügbare Befehle für sich wiederholende Aufgaben gibt, die jeder WordPress-Entwickler oder Website-Betreuer täglich oder wöchentlich ausführt. Diese Befehle haben mir im Laufe des Jahres unzählige Stunden des Zeigens, Klickens und Wartens auf das Neuladen von Seiten erspart.

Sind Sie überzeugt? Bereit anzufangen? Toll!

Sie müssen WP-CLI mit Ihrem WordPress (oder global auf Ihrem lokalen Computer) installiert haben. Wenn Sie WP-CLI noch nicht auf Ihrer lokalen Entwicklungsumgebung installiert haben, finden Sie eine Installationsanleitung auf der Website hier. Wenn Sie Varying Vagrant Vagrants (VVV2) verwenden, ist WP-CLI enthalten. Viele Hosting-Anbieter haben auch WP-CLI auf ihrer Plattform integriert. Ich gehe davon aus, dass Sie dies in Zukunft erfolgreich installiert haben.

Verwenden von WP-CLI zum Lösen des Problems

Um das Problem der sich wiederholenden Aufgaben zu lösen, müssen wir unserer WordPress-Installation einen benutzerdefinierten WP-CLI-Befehl zur Verfügung stellen. Eine der einfachsten Möglichkeiten, einer Website Funktionen hinzuzufügen, besteht darin, ein Plugin zu erstellen. Wir werden in diesem Fall aus drei Hauptgründen ein Plugin verwenden:

  1. Wir können den benutzerdefinierten Befehl deaktivieren, wenn wir ihn nicht benötigen
  2. Wir können unsere Befehle und Unterbefehle leicht erweitern, während wir die Dinge modular halten.
  3. Wir können die Funktionalität über Themen und sogar andere WordPress-Installationen hinweg aufrechterhalten.

Erstellen des Plugins

Um ein Plugin zu erstellen, müssen wir ein Verzeichnis zu unserem /plugins -Verzeichnis in unserem wp-content Verzeichnis hinzufügen. Wir können dieses Verzeichnis toptal-wpcli . Erstellen Sie dann zwei Dateien in diesem Verzeichnis:

  • index.php , die nur eine Codezeile haben sollte: <?php // Silence is golden
  • plugin.php , wo unser Code hinkommt (Sie können diese Datei beliebig benennen.)

Öffnen Sie die Datei plugin.php und fügen Sie den folgenden Code hinzu:

 <?php /** * Plugin Name: TOPTAL WP-CLI Commands * Version: 0.1 * Plugin URI: https://n8finch.com/ * Description: Some rando wp-cli commands to make life easier... * Author: Nate Finch * Author URI: https://n8finch.com/ * Text Domain: toptal-wpcli * Domain Path: /languages/ * License: GPL v3 */ /** * NOTE: THIS PLUGIN FILE WILL NOT WORK IN PRODUCTION AS IS AND IS ONLY FOR DEMONSTRATION PURPOSES! * You can of course take the code and repurpose it:-). */ if ( !defined( 'WP_CLI' ) && WP_CLI ) { //Then we don't want to load the plugin return; }

Diese ersten Zeilen bestehen aus zwei Teilen.

Zuerst haben wir den Plugin-Header. Diese Informationen werden auf die Admin-Seite der WordPress-Plugins gezogen und ermöglichen es uns, unser Plugin zu registrieren und zu aktivieren. Nur der Plugin-Name ist erforderlich, aber wir sollten den Rest für alle angeben, die diesen Code verwenden möchten (sowie für unser zukünftiges Selbst!).

Zweitens wollen wir überprüfen, ob WP-CLI definiert ist. Das heißt, wir prüfen, ob die WP-CLI-Konstante vorhanden ist. Wenn dies nicht der Fall ist, möchten wir das Plugin bailen und nicht ausführen. Wenn es vorhanden ist, können wir den Rest unseres Codes ausführen.

Zwischen diesen beiden Abschnitten habe ich einen Hinweis hinzugefügt, dass dieser Code nicht „wie er ist“ in der Produktion verwendet werden sollte, da einige der Funktionen Platzhalter für echte Funktionen sind. Wenn Sie diese Platzhalterfunktionen in echte, aktive Funktionen umwandeln, können Sie diesen Hinweis gerne löschen.

Hinzufügen des benutzerdefinierten Befehls

Als nächstes wollen wir den folgenden Code einfügen:

 class TOPTAL_WP_CLI_COMMANDS extends WP_CLI_Command { function remove_user() { echo "\n\n hello world \n\n"; } } WP_CLI::add_command( 'toptal', 'TOPTAL_WP_CLI_COMMANDS' );

Dieser Codeblock erledigt zwei Dinge für uns:

  1. Es definiert die Klasse TOPTAL_WP_CLI_COMMANDS , an die wir Argumente übergeben können.
  2. Es weist der Klasse den Befehl toptal zu, sodass wir ihn von der Befehlszeile aus ausführen können.

Wenn wir nun wp toptal remove_user ausführen, sehen wir:

 $ wp toptal hello hello world

Das bedeutet, dass unser Befehl toptal registriert ist und unser Unterbefehl remove_user funktioniert.

Variablen einrichten

Da wir eine Massenverarbeitung durchführen, um Benutzer zu entfernen, möchten wir die folgenden Variablen einrichten:

 // Keep a tally of warnings and loops $total_warnings = 0; $total_users_removed = 0; // If it's a dry run, add this to the end of the success message $dry_suffix = ''; // Keep a list of emails for users we may want to double check $emails_not_existing = array(); $emails_without_level = array(); // Get the args $dry_run = $assoc_args['dry-run']; $level = $assoc_args['level']; $emails = explode( ',', $assoc_args['email'] );

Die Absicht jeder der Variablen ist wie folgt:

  • total_warnings : Wir zählen eine Warnung, wenn die E-Mail nicht existiert oder wenn die E-Mail nicht mit der Mitgliedschaftsstufe verknüpft ist, die wir entfernen.
  • $total_users_removed : Wir möchten die Anzahl der Benutzer zählen, die während des Vorgangs entfernt wurden (siehe Einschränkung unten).
  • $dry_suffix : Wenn dies ein Probelauf ist, möchten wir der endgültigen Erfolgsmeldung einen Wortlaut hinzufügen.
  • $emails_not_existing : Speichert eine Liste von E-Mails, die nicht existieren.
  • $emails_without_level : Speichert eine Liste von E-Mails, die nicht das angegebene Level haben.
  • $dry_run : Ein boolescher Wert, der speichert, ob das Skript einen Probelauf durchführt (true) oder nicht (false).
  • $level : Eine Ganzzahl, die das Level darstellt, das überprüft und möglicherweise entfernt werden soll.
  • $email : Ein Array von E-Mails, die mit dem angegebenen Level abgeglichen werden. Wir werden dieses Array durchlaufen

Wenn unsere Variablen gesetzt sind, können wir die Funktion tatsächlich ausführen. In echter WordPress-Manier werden wir eine Schleife ausführen.

Die Funktion selbst schreiben

Wir beginnen mit der Erstellung einer foreach -Schleife, um alle E-Mails in unserem $emails Array zu durchlaufen:

 // Loop through emails foreach ( $emails as $email ) { // code coming soon } // end foreach

Dann fügen wir eine bedingte Prüfung hinzu:

 // Loop through emails foreach ( $emails as $email ) { //Get User ID $user_id = email_exists($email); if( !$user_id ) { WP_CLI::warning( "The user {$email} does not seem to exist." ); array_push( $emails_not_existing, $email ); $total_warnings++; continue; } } // end foreach

Diese Überprüfung stellt sicher, dass wir einen registrierten Benutzer mit der E-Mail haben, die wir überprüfen. Es verwendet die Funktion email_exists() , um zu prüfen, ob es einen Benutzer mit dieser E-Mail gibt. Wenn es keinen Benutzer mit dieser E-Mail findet, wird eine Warnung ausgegeben, damit wir auf unserem Terminalbildschirm wissen, dass die E-Mail nicht gefunden wurde:

 $ wp toptal remove_user [email protected] --dry-run Warning: The user [email protected] does not seem to exist.

Die E-Mail wird dann zur späteren Anzeige im Array $emails_not_existing gespeichert. Dann erhöhen wir die Gesamtwarnung um eins und fahren durch die Schleife mit der nächsten E-Mail fort.

Wenn die E-Mail existiert, verwenden wir die $user_id und die $level Variablen, um zu prüfen, ob der Benutzer Zugriff auf das Level hat. Wir speichern den resultierenden booleschen Wert in der Variablen $has_level :

 // Loop through emails foreach ( $emails as $email ) { //Get User ID $user_id = email_exists($email); if( !$user_id ) { WP_CLI::warning( "The user {$email} does not seem to exist." ); array_push( $emails_not_existing, $email ); $total_warnings++; continue; } // Check membership level. This is a made up function, but you could write one or your membership plugin probably has one. $has_level = function_to_check_membership_level( $level, $user_id ); } // end foreach

Wie die meisten Funktionen in diesem Beispiel ist diese function_to_check_membership_level() fabriziert, aber die meisten Mitgliedschafts-Plugins sollten Hilfsfunktionen haben, um Ihnen diese Informationen zu geben.

Jetzt kommen wir zur Hauptaktion: dem Entfernen des Levels vom Benutzer. Wir verwenden eine if/else -Struktur, die so aussieht:

 foreach ( $emails as $email ) { // Previous code here... // Check membership level. This is a made up function, but you could write one or your membership plugin probably has one. $has_level = function_to_check_membership_level( $level, $user_id ); if ( $has_level ) { if ( !$dry_run ) { // Deactivate membership level. This is a made up function, but you could write one or your membership plugin probably has one. function_to_deactivate_membership_level( $level, $user_id, 'inactive' ); } WP_CLI::success( "Membership canceled for {$email}, Level {$level} removed" . PHP_EOL ); $total_users_removed++; } else { WP_CLI::warning( "The user {$email} does not have Level = {$level} membership." ); array_push( $emails_without_level, $email ); $total_warnings++; } // We could echo something here to show that things are processing... } // end foreach

Wenn der Wert von $has_level „truthy“ ist, was bedeutet, dass der Benutzer Zugriff auf die Mitgliedschaftsebene hat, möchten wir eine Funktion ausführen, um diese Ebene zu entfernen. In diesem Beispiel verwenden wir die function_to_deactivate_membership_level() , um diese Aktion auszuführen.

Bevor wir das Level jedoch tatsächlich vom Benutzer entfernen, möchten wir diese Funktion in eine bedingte Prüfung einschließen, um festzustellen, ob es sich tatsächlich um einen dry-run handelt. Wenn dies der Fall ist, möchten wir nichts entfernen, sondern lediglich melden, dass wir dies getan haben. Wenn es sich nicht um einen dry-run Mails weiter durchlaufen.

Wenn andererseits der Wert von $has_level „falsey“ ist, was bedeutet, dass der Benutzer keinen Zugriff auf die Mitgliedschaftsebene hat, möchten wir eine Warnung an das Terminal protokollieren, die E-Mail in das Array $emails_without_level und fortfahren Schleife durch die E-Mails.

Abschluss und Berichterstattung

Sobald die Schleife beendet ist, möchten wir unsere Ergebnisse in der Konsole protokollieren. Wenn dies ein Probelauf war, möchten wir eine zusätzliche Nachricht an die Konsole protokollieren:

 if ( $dry_run ) { $dry_suffix = 'BUT, nothing really changed because this was a dry run:-).'; }

Dieses $dry-suffix wird an die Warnungen und Erfolgsmeldungen angehängt, die wir als Nächstes protokollieren.

Abschließend möchten wir unsere Ergebnisse als Erfolgsmeldung und unsere Warnungen als Warnmeldungen protokollieren. Wir werden dies folgendermaßen tun:

 WP_CLI::success( "{$total_users_removed} User/s been removed, with {$total_warnings} warnings. {$dry_suffix}" ); if ( $total_warnings ) { $emails_not_existing = implode(',', $emails_not_existing); $emails_without_level = implode(',', $emails_without_level); WP_CLI::warning( "These are the emails to double check and make sure things are on the up and up:" . PHP_EOL . "Non-existent emails: " . $emails_not_existing . PHP_EOL . "Emails without the associated level: " . $emails_without_level . PHP_EOL ); }

Beachten Sie, dass wir die WP_CLI::success und WP_CLI::warning verwenden. Diese werden von WP-CLI bereitgestellt, um Informationen an die Konsole zu protokollieren. Sie können Zeichenfolgen einfach protokollieren, was wir hier tun, einschließlich unserer $total_users_removed , $total_warnings und $dry_suffix .

Wenn wir schließlich während der Laufzeit des Skripts Warnungen erhalten haben, möchten wir diese Informationen auf der Konsole ausgeben. Nachdem wir eine Bedingungsprüfung durchgeführt haben, konvertieren wir die Array-Variablen $emails_not_existing und $emails_without_level in String-Variablen. Wir tun dies, damit wir sie mit der WP_CLI::warning auf der Konsole ausgeben können.

Hinzufügen einer Beschreibung

Wir alle wissen, dass Kommentare für andere und unser zukünftiges Selbst hilfreich sind, wenn wir Wochen, Monate oder sogar Jahre später zu unserem Code zurückkehren. WP-CLI bietet eine Schnittstelle mit kurzen Beschreibungen (shortdesc) und langen Beschreibungen (longdesc), die es uns ermöglicht, unseren Befehl zu kommentieren. Wir werden an den Anfang unseres Befehls setzen, nachdem die Klasse TOPTAL_WP_CLI_COMMANDS definiert wurde:

 /** * Remove a membership level from a user * * ## OPTIONS * --level=<number> * : Membership level to check for and remove * * --email=<email> * : Email of user to check against * * [--dry-run] * : Run the entire search/replace operation and show report, but don't save changes to the database. * * ## EXAMPLES * * wp toptal remove_user --level=5 [email protected],[email protected], [email protected] --dry-run * * @when after_wp_load */

In longdesc definieren wir, was wir von unserem benutzerdefinierten Befehl erwarten. Die Syntax für shortdesc und longdesc ist Markdown Extra. Unter dem Abschnitt ## OPTIONS definieren wir die Argumente, die wir erwarten. Wenn ein Argument erforderlich ist, schließen wir es in < > ein, und wenn es optional ist, schließen wir es in [ ] ein.

Diese Optionen werden validiert, wenn der Befehl ausgeführt wird; Wenn wir beispielsweise den erforderlichen E-Mail-Parameter weglassen, erhalten wir die folgende Fehlermeldung:

 $ wp toptal remove_user --level=5 --dry-run Error: Parameter errors: missing --email parameter (Email of user to check against)

Der Abschnitt ## EXAMPLES enthält ein Beispiel dafür, wie der Befehl aussehen könnte, wenn er aufgerufen wird.

Unser benutzerdefinierter Befehl ist jetzt abgeschlossen. Sie können den endgültigen Kern hier sehen.

Ein Vorbehalt und Raum für Verbesserungen

Es ist wichtig, die Arbeit, die wir hier geleistet haben, zu überprüfen, um zu sehen, wie der Code verbessert, erweitert und umgestaltet werden könnte. Es gibt viele Verbesserungsbereiche für dieses Skript. Hier sind einige Beobachtungen über Verbesserungen, die gemacht werden könnten.

Gelegentlich habe ich festgestellt, dass dieses Skript nicht alle Benutzer entfernt, die es als „entfernt“ protokolliert. Dies liegt höchstwahrscheinlich daran, dass das Skript schneller ausgeführt wird, als die Abfragen ausgeführt werden können. Ihre Erfahrung kann je nach Umgebung und Setup, in dem das Skript ausgeführt wird, unterschiedlich sein. Der schnelle Weg, dies zu umgehen, besteht darin, wiederholt mit denselben Eingaben zu arbeiten. Es wird schließlich auf Null gesetzt und gemeldet, dass keine Benutzer entfernt wurden.

Das Skript könnte verbessert werden, um zu warten und zu validieren, dass ein Benutzer entfernt wurde, bevor der Benutzer als tatsächlich entfernt protokolliert wird. Dies würde die Ausführung des Skripts verlangsamen, wäre aber genauer und Sie müssten es nur einmal ausführen.

Wenn solche Fehler gefunden wurden, könnte das Skript auf ähnliche Weise Fehler ausgeben, um darauf hinzuweisen, dass eine Ebene nicht von einem Benutzer entfernt wurde.

Ein weiterer Bereich zur Verbesserung des Skripts besteht darin, dass mehrere Ebenen gleichzeitig von einer E-Mail-Adresse entfernt werden können. Das Skript könnte automatisch erkennen, ob eine oder mehrere Ebenen und eine oder mehrere E-Mails entfernt werden müssen. Ich erhielt CSV-Dateien nach Level, sodass ich jeweils nur ein Level ausführen musste.

Wir könnten auch einen Teil des Codes umgestalten, um ternäre Operatoren anstelle der ausführlicheren bedingten Prüfungen zu verwenden, die wir derzeit haben. Ich habe mich entschieden, dies zu Demonstrationszwecken leichter lesbar zu machen, aber fühlen Sie sich frei, den Code zu Ihrem eigenen zu machen.

Anstatt E-Mails im letzten Schritt auf der Konsole zu drucken, könnten wir sie im letzten Schritt auch automatisch in eine CSV- oder reine Textdatei exportieren

Schließlich gibt es keine Überprüfungen, um sicherzustellen, dass wir eine Ganzzahl für die $level -Variable oder eine E-Mail oder eine durch Kommas getrennte Liste von E-Mails in der $emails -Variablen erhalten. Wenn derzeit jemand Zeichenfolgen anstelle von Ganzzahlen oder Benutzeranmeldenamen anstelle von E-Mails einfügen würde, würde das Skript nicht funktionieren (und keine Fehler ausgeben). Überprüfungen auf Ganzzahlen und E-Mails könnten hinzugefügt werden.

Ideen zur weiteren Automatisierung und weiterführende Literatur

Wie Sie sehen können, ist WP-CLI selbst in diesem speziellen Anwendungsfall ziemlich flexibel und leistungsstark genug, um Ihnen zu helfen, Ihre Arbeit schnell und effizient zu erledigen. Sie fragen sich vielleicht: „Wie kann ich mit der Implementierung von WP-CLI in meinem täglichen und wöchentlichen Entwicklungsablauf beginnen?“

Es gibt mehrere Möglichkeiten, wie Sie WP-CLI verwenden können. Hier sind einige meiner Favoriten:

  • Aktualisieren Sie Themen, Plugins und den WP-Kern, ohne in das Admin-Panel gehen zu müssen.
  • Exportieren Sie Datenbanken zur Sicherung oder führen Sie einen schnellen SQL-Dump durch, wenn ich eine SQL-Abfrage testen möchte.
  • Migrieren Sie WordPress-Sites.
  • Installieren Sie neue WordPress-Sites mit Dummy-Daten oder benutzerdefinierten Plugin-Suite-Setups.
  • Führen Sie Prüfsummen für Kerndateien aus, um sicherzustellen, dass sie nicht kompromittiert wurden. (Es ist tatsächlich ein Projekt im Gange, um dies auf Themen und Plugins im WP-Repo auszudehnen.)
  • Schreiben Sie Ihr eigenes Skript, um Site-Hosts zu überprüfen, zu aktualisieren und zu warten (worüber ich hier geschrieben habe).

Die Möglichkeiten mit WP-CLI sind nahezu grenzenlos. Hier sind einige Ressourcen, die Sie voranbringen:

  • Die Hauptseite von WP-CLI: http://wp-cli.org
  • WP-CLI-Befehle: https://developer.wordpress.org/cli/commands/
  • Offizieller WP-CLI-Blog: https://make.wordpress.org/cli/
  • WP-CLI-Handbuch: https://make.wordpress.org/cli/handbook/
  • In WooCommerce? Überprüfen Sie die WC-CLI: https://github.com/woocommerce/woocommerce/wiki/WC-CLI-Overview#woocommerce-commands
  • Podcast-Interview mit Daniel Bachhuber, Betreuer des Projekts: https://howibuilt.it/episode-28-daniel-bachhuber-wp-cli/