Nie powtarzaj się: automatyzacja powtarzalnych zadań za pomocą WP-CLI
Opublikowany: 2022-03-11Czy kiedykolwiek znalazłeś się w obszarze administracyjnym WordPress, aby zaktualizować motywy, wtyczki i rdzeń WP? Oczywiście, że masz. Czy zapytano Cię: „Czy możesz utworzyć/zaktualizować/usunąć wszystkich użytkowników w tym pliku CSV?” Jestem pewien, że ty też na to wpadłeś. Czy próbowałeś migrować witrynę i żałowałeś, że nie ma wtyczki lub narzędzia innej firmy, po które możesz sięgnąć, aby wykonać tę pracę? Wiem, że mam!
Dostępne jest bardzo potężne narzędzie, które pomoże Ci w tych zadaniach i nie tylko. Zanim o tym opowiem, chciałbym ułożyć krótką anegdotę.
Problem: W ostatnim projekcie było kilka zadań programistycznych, które musiałem regularnie powtarzać. Jedno zadanie w szczególności dotyczyło aktualizacji uprawnień na poziomie użytkownika na podstawie dowodów zakupu lub subskrypcji na poziomie członkostwa. Jeśli firma nie mogła znaleźć płatności od użytkownika za określony poziom członkostwa, chciała, aby poziom członkostwa został usunięty z użytkownika. Dlaczego było to potrzebne? Być może członek zatrzymał subskrypcję, ale wydarzenie się nie uruchomiło, a zatem członek nadal ma dostęp, nawet jeśli za to nie płaci (ojej!). A może ktoś korzystał z oferty próbnej, ale oferta wygasła, a klient nadal ma abonament (także obla!).
Rozwiązanie: Zamiast wchodzić do panelu administratora i ręcznie usuwać setki (może tysiące) subskrypcji, zdecydowałem się sięgnąć po jedno z moich ulubionych narzędzi WordPressa, WP-CLI, które naprawiło problem za pomocą kilku naciśnięć klawiszy.
W tym poście chcę przedstawić WP-CLI (zakładając, że nie jesteście już bliskimi przyjaciółmi), przeprowadzić Cię przez proste niestandardowe polecenie, które napisałem dla tej konkretnej sytuacji, i podać kilka pomysłów i zasobów dotyczących korzystania z WP-CLI w własny rozwój.
Co to jest WP-CLI?
Jeśli nigdy wcześniej nie słyszałeś o WP-CLI, nie jesteś sam. Projekt, choć miał kilka lat, przez jakiś czas wydawał się być pod radarem WordPressa. Oto krótki opis tego, czym jest i robi WP-CLI z oficjalnej strony internetowej:
WP-CLI to zestaw narzędzi wiersza poleceń do zarządzania instalacjami WordPress. Możesz aktualizować wtyczki, konfigurować instalacje wielostanowiskowe i wiele więcej bez korzystania z przeglądarki internetowej.
Poniższe polecenia pokazują moc WP-CLI po wyjęciu z pudełka:
-
wp plugin update --all
aktualizuje wszystkie aktualizowalne wtyczki. -
wp db export
eksportuje zrzut SQL bazy danych. -
wp media regenerate
regeneruje miniatury załączników (np. po zmianie rozmiaru w motywie). -
wp checksum core
sprawdza, czy pliki rdzenia WordPress nie zostały naruszone. -
wp search-replace
wyszukuje i zamienia ciągi w bazie danych.
Jeśli odkryjesz więcej poleceń tutaj, zobaczysz, że istnieje wiele dostępnych poleceń dla powtarzalnych zadań, które każdy programista WordPress lub opiekun witryny wykonuje codziennie lub co tydzień. Te polecenia zaoszczędziły mi niezliczonych godzin wskazywania, klikania i czekania na ponowne załadowanie strony w ciągu roku.
Czy jesteś przekonany? Gotowy żeby zacząć? Świetnie!
Będziesz musiał mieć zainstalowany WP-CLI z WordPress (lub globalnie na komputerze lokalnym). Jeśli nie zainstalowałeś jeszcze WP-CLI w lokalnym środowisku programistycznym, instrukcje instalacji można znaleźć na stronie internetowej tutaj. Jeśli używasz Varying Vagrant Vagrants (VVV2), dołączony jest WP-CLI. Wielu dostawców hostingu ma również WP-CLI na swojej platformie. Zakładam, że udało Ci się to pomyślnie zainstalować.
Używanie WP-CLI do rozwiązania problemu
Aby rozwiązać problem powtarzających się zadań, musimy udostępnić niestandardową komendę WP-CLI naszej instalacji WordPress. Jednym z najprostszych sposobów na dodanie funkcjonalności do dowolnej witryny jest stworzenie wtyczki. W tym przypadku użyjemy wtyczki z trzech głównych powodów:
- Będziemy mogli wyłączyć niestandardowe polecenie, jeśli go nie potrzebujemy
- Możemy łatwo rozszerzać nasze polecenia i podkomendy, zachowując jednocześnie modułowość.
- Możemy utrzymać funkcjonalność w różnych motywach, a nawet w innych instalacjach WordPress.
Tworzenie wtyczki
Aby utworzyć wtyczkę, musimy dodać katalog do naszego katalogu /plugins
w naszym katalogu wp-content
. Możemy nazwać ten katalog toptal-wpcli
. Następnie utwórz dwa pliki w tym katalogu:
-
index.php
, który powinien mieć tylko jedną linię kodu:<?php // Silence is golden
-
plugin.php
, do którego trafi nasz kod (możesz nazwać ten plik, jak chcesz.)
Otwórz plik plugin.php
i dodaj następujący kod:
<?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; }
Te kilka pierwszych linijek składa się z dwóch części.
Najpierw mamy nagłówek wtyczki. Te informacje są pobierane na stronę administratora wtyczek WordPress i pozwalają nam zarejestrować naszą wtyczkę i ją aktywować. Wymagana jest tylko nazwa wtyczki, ale powinniśmy uwzględnić resztę dla każdego, kto chciałby użyć tego kodu (a także dla nas w przyszłości!).
Po drugie, chcemy sprawdzić, czy zdefiniowano WP-CLI. Oznacza to, że sprawdzamy, czy występuje stała WP-CLI. Jeśli tak nie jest, chcemy wypłacić kaucję i nie uruchamiać wtyczki. Jeśli jest obecny, możemy uruchomić resztę naszego kodu.
Pomiędzy tymi dwiema sekcjami dodałem uwagę, że ten kod nie powinien być używany „tak jak jest” w środowisku produkcyjnym, ponieważ niektóre funkcje są symbolami zastępczymi dla funkcji rzeczywistych. Jeśli zmienisz te funkcje zastępcze na rzeczywiste, aktywne funkcje, możesz usunąć tę notatkę.
Dodawanie niestandardowego polecenia
Następnie chcemy dołączyć następujący kod:
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' );
Ten blok kodu robi dla nas dwie rzeczy:
- Definiuje klasę
TOPTAL_WP_CLI_COMMANDS
, do której możemy przekazać argumenty. - Przypisuje
toptal
polecenia do klasy, więc możemy go uruchomić z wiersza poleceń.
Teraz, jeśli wykonamy wp toptal remove_user
, zobaczymy:
$ wp toptal hello hello world
Oznacza to, że nasza komenda toptal
jest zarejestrowana i nasza remove_user
działa.
Konfigurowanie zmiennych
Ponieważ przetwarzamy zbiorczo, usuwając użytkowników, chcemy skonfigurować następujące zmienne:
// 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'] );
Intencja każdej ze zmiennych jest następująca:
-
total_warnings
: Wyświetlimy ostrzeżenie, jeśli wiadomość e-mail nie istnieje lub jeśli wiadomość e-mail nie jest powiązana z usuwanym poziomem członkostwa. -
$total_users_removed
: Chcemy zliczyć liczbę użytkowników usuniętych w procesie (patrz zastrzeżenie poniżej). -
$dry_suffix
: Jeśli jest to próba, chcemy dodać sformułowania do końcowego powiadomienia o sukcesie. -
$emails_not_existing
: Przechowuje listę nieistniejących e-maili. -
$emails_without_level
: Przechowuje listę e-maili, które nie mają określonego poziomu. -
$dry_run
: Wartość logiczna, która przechowuje informację, czy skrypt wykonuje test na sucho (prawda), czy nie (fałsz). -
$level
: liczba całkowita reprezentująca poziom do sprawdzenia i ewentualnie usunięcia. -
$email
: Tablica e-maili do sprawdzenia na podanym poziomie. Przejdziemy przez tę tablicę
Po ustawieniu naszych zmiennych jesteśmy gotowi do faktycznego uruchomienia funkcji. W prawdziwym stylu WordPressa uruchomimy pętlę.
Pisanie samej funkcji
Zaczynamy od utworzenia pętli foreach
, która przejdzie przez wszystkie e-maile w naszej tablicy $emails
:
// Loop through emails foreach ( $emails as $email ) { // code coming soon } // end foreach
Następnie dodajemy kontrolę warunkową:
// 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
To sprawdzenie gwarantuje, że mamy zarejestrowanego użytkownika z adresem e-mail, który sprawdzamy. Używa funkcji email_exists()
, aby sprawdzić, czy istnieje użytkownik z tym adresem e-mail. Jeśli nie znajdzie użytkownika z tym e-mailem, wygeneruje ostrzeżenie, abyśmy wiedzieli na ekranie naszego terminala, że e-mail nie został znaleziony:
$ wp toptal remove_user [email protected] --dry-run Warning: The user [email protected] does not seem to exist.
Wiadomość e-mail jest następnie przechowywana w tablicy $emails_not_existing
do późniejszego wyświetlenia. Następnie zwiększamy całkowite ostrzeżenie o jeden i przechodzimy przez pętlę do następnego e-maila.
Jeśli wiadomość e-mail istnieje, użyjemy zmiennych $user_id
i $level
, aby sprawdzić, czy użytkownik ma dostęp do danego poziomu. Otrzymaną wartość logiczną przechowujemy w zmiennej $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
Podobnie jak większość funkcji w tym przykładzie, ta function_to_check_membership_level()
jest sfabrykowana, ale większość wtyczek członkowskich powinna mieć funkcje pomocnicze, aby uzyskać te informacje.
Teraz przejdziemy do głównej akcji: usunięcia poziomu z użytkownika. Użyjemy struktury if/else
, która wygląda tak:
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
Jeśli wartość $has_level
to „prawda”, co oznacza, że użytkownik ma dostęp do poziomu członkostwa, chcemy uruchomić funkcję usuwającą ten poziom. W tym przykładzie użyjemy function_to_deactivate_membership_level()
do wykonania tej akcji.
Jednak zanim faktycznie usuniemy poziom z użytkownika, chcemy ująć tę funkcję w warunkowym sprawdzeniu, aby zobaczyć, czy jest to rzeczywiście dry-run
. Jeśli tak, nie chcemy niczego usuwać, a jedynie zgłosić, że to zrobiliśmy. Jeśli nie jest to dry-run
, wtedy usuniemy poziom z użytkownika, zarejestrujemy naszą wiadomość o sukcesie w terminalu i kontynuujemy przeglądanie wiadomości e-mail.
Jeśli z drugiej strony wartość $has_level
to „falsey”, co oznacza, że użytkownik nie ma dostępu do poziomu członkostwa, chcemy zarejestrować ostrzeżenie w terminalu, przekazać wiadomość e-mail do tablicy $emails_without_level
i kontynuować przeglądanie e-maili.
Wykańczanie i raportowanie
Po zakończeniu pętli chcemy zarejestrować nasze wyniki w konsoli. Jeśli to była próba, chcemy zarejestrować w konsoli dodatkowy komunikat:
if ( $dry_run ) { $dry_suffix = 'BUT, nothing really changed because this was a dry run:-).'; }
Ten $dry-suffix
zostanie dołączony do ostrzeżeń i powiadomień o sukcesie, które rejestrujemy w następnej kolejności.
Kończąc, chcemy rejestrować nasze wyniki jako komunikat o sukcesie, a nasze ostrzeżenia jako komunikaty ostrzegawcze. Zrobimy to tak:
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 ); }
Zauważ, że używamy metod pomocniczych WP_CLI::success
i WP_CLI::warning
. Są one dostarczane przez WP-CLI do rejestrowania informacji w konsoli. Możesz łatwo rejestrować łańcuchy, co robimy tutaj, w tym nasze $total_users_removed
, $total_warnings
i $dry_suffix
.
Na koniec, jeśli w trakcie działania skryptu pojawiły się jakiekolwiek ostrzeżenia, chcemy wydrukować te informacje na konsoli. Po uruchomieniu sprawdzania warunkowego konwertujemy zmienne tablicowe $emails_not_existing
i $emails_without_level
na zmienne łańcuchowe. Robimy to, abyśmy mogli wydrukować je na konsoli za pomocą metody pomocniczej WP_CLI::warning
.
Dodawanie opisu
Wszyscy wiemy, że komentarze są pomocne dla innych i dla nas w przyszłości, wracając do naszego kodu tygodnie, miesiące, a nawet lata później. WP-CLI zapewnia interfejs krótkich opisów (shortdesc) i długich opisów (longdesc), który pozwala nam dodawać adnotacje do naszego polecenia. Umieścimy na górze naszego polecenia, po zdefiniowaniu klasy TOPTAL_WP_CLI_COMMANDS
:
/** * 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 */
W longdesc definiujemy, czego oczekujemy od naszego niestandardowego polecenia. Składnia skrótów shortdesc i longdesc to Markdown Extra. W sekcji ## OPTIONS
definiujemy argumenty, które oczekujemy otrzymać. Jeśli argument jest wymagany, zawijamy go w < >
, a jeśli jest opcjonalny, zawijamy go w [ ]
.
Te opcje są sprawdzane po uruchomieniu polecenia; na przykład, jeśli pominiemy wymagany parametr adresu e-mail, otrzymamy następujący błąd:
$ wp toptal remove_user --level=5 --dry-run Error: Parameter errors: missing --email parameter (Email of user to check against)
Sekcja ## EXAMPLES
zawiera przykład tego, jak polecenie może wyglądać po wywołaniu.
Nasze niestandardowe polecenie jest teraz gotowe. Ostateczny sens można zobaczyć tutaj.
Zastrzeżenie i miejsce na ulepszenia
Ważne jest, aby przejrzeć pracę, którą tutaj wykonaliśmy, aby zobaczyć, jak można ulepszyć, rozszerzyć i zrefaktoryzować kod. Istnieje wiele obszarów usprawnień tego skryptu. Oto kilka spostrzeżeń na temat ulepszeń, które można wprowadzić.
Czasami stwierdzam, że ten skrypt nie usunie wszystkich użytkowników, których rejestruje jako „usuniętych”. Jest to najprawdopodobniej spowodowane tym, że skrypt działa szybciej niż mogą wykonać zapytania. Twoje wrażenia mogą się różnić w zależności od środowiska i konfiguracji, w której skrypt jest uruchamiany. Szybkim sposobem na obejście tego jest wielokrotne uruchamianie z tymi samymi danymi wejściowymi; w końcu wyzeruje się i zgłosi, że żaden użytkownik nie został usunięty.
Skrypt można ulepszyć, aby czekał i sprawdzał, czy użytkownik został usunięty, przed zalogowaniem użytkownika jako faktycznie usuniętego. Spowolniłoby to wykonanie skryptu, ale byłoby bardziej dokładne i wystarczyłoby go uruchomić tylko raz.
Podobnie, jeśli zostaną znalezione takie błędy, skrypt może zgłosić błędy, aby ostrzec, że poziom nie został usunięty z użytkownika.
Innym obszarem, w którym można ulepszyć skrypt, jest umożliwienie jednoczesnego usuwania wielu poziomów z jednego adresu e-mail. Skrypt mógł automatycznie wykryć, czy istnieje co najmniej jeden poziom i co najmniej jeden e-mail do usunięcia. Dostałem pliki CSV według poziomów, więc musiałem uruchamiać tylko jeden poziom na raz.
Moglibyśmy również przerobić część kodu, aby używać operatorów trójargumentowych zamiast bardziej szczegółowych kontroli warunkowych, które obecnie mamy. Zdecydowałem się ułatwić czytanie ze względu na demonstrację, ale możesz stworzyć własny kod.
W ostatnim kroku, zamiast drukować e-maile do konsoli w ostatnim kroku, możemy również automatycznie wyeksportować je do pliku CSV lub zwykłego tekstu
Wreszcie, nie ma żadnych sprawdzeń, aby upewnić się, że otrzymujemy liczbę całkowitą dla zmiennej $level
lub wiadomość e-mail lub listę e-maili oddzielonych przecinkami w zmiennej $emails
. Obecnie, gdyby ktoś zamiast liczb całkowitych dołączył ciągi znaków lub nazwy logowania użytkowników zamiast e-maili, skrypt nie działałby (i nie zgłaszałby błędów). Można dodać czeki na liczby całkowite i e-maile.
Pomysły na dalszą automatyzację i dalsze czytanie
Jak widać, nawet w tym konkretnym przypadku użycia WP-CLI jest dość elastyczny i wystarczająco wydajny, aby pomóc Ci szybko i wydajnie wykonać pracę. Być może zastanawiasz się: „Jak mogę zacząć wdrażać WP-CLI w moim codziennym i cotygodniowym przepływie rozwoju?”
Istnieje kilka sposobów korzystania z WP-CLI. Oto niektóre z moich ulubionych:
- Aktualizuj motywy, wtyczki i rdzeń WP bez konieczności wchodzenia do panelu administracyjnego.
- Eksportuj bazy danych w celu wykonania kopii zapasowej lub wykonaj szybki zrzut SQL, jeśli chcę przetestować zapytanie SQL.
- Przenieś witryny WordPress.
- Zainstaluj nowe witryny WordPress z fikcyjnymi danymi lub niestandardowymi konfiguracjami pakietu wtyczek.
- Uruchom sumy kontrolne plików podstawowych, aby upewnić się, że nie zostały one naruszone. (W rzeczywistości trwa projekt rozszerzenia tego na motywy i wtyczki w repozytorium WP.)
- Napisz własny skrypt do sprawdzania, aktualizowania i obsługi hostów witryny (o czym pisałem tutaj).
Możliwości z WP-CLI są prawie nieograniczone. Oto kilka zasobów, które pomogą Ci iść naprzód:
- Główna strona WP-CLI: http://wp-cli.org
- Polecenia WP-CLI: https://developer.wordpress.org/cli/commands/
- Oficjalny blog WP-CLI: https://make.wordpress.org/cli/
- Podręcznik WP-CLI: https://make.wordpress.org/cli/handbook/
- W WooCommerce? Sprawdź WC-CLI: https://github.com/woocommerce/woocommerce/wiki/WC-CLI-Overview#woocommerce-commands
- Podcast Wywiad z Danielem Bachhuberem, opiekunem projektu: https://howibuilt.it/episode-28-daniel-bachhuber-wp-cli/