자신을 반복하지 마십시오: WP-CLI로 반복 작업 자동화

게시 됨: 2022-03-11

테마, 플러그인 및 WP 코어를 업데이트하기 위해 WordPress 관리 영역으로 이동한 적이 있습니까? 물론 있습니다. "이 CSV 파일의 모든 사용자를 생성/업데이트/삭제할 수 있습니까?"라는 질문을 받은 적이 있습니까? 나는 당신도 그것에 부딪쳤다고 확신합니다. 사이트 마이그레이션을 시도하고 작업을 수행하기 위해 연결할 수 있는 플러그인이나 타사 도구가 있기를 바랐습니까? 알고 있어요!

WP-CLI로 반복 작업 자동화

이러한 작업 등을 수행하는 데 사용할 수 있는 매우 강력한 도구가 있습니다. 그 이야기를 하기 전에 간단한 일화 하나를 하나 준비하겠습니다.

문제: 최근 프로젝트에서 정기적으로 반복해야 하는 몇 가지 프로그래밍 작업이 있었습니다. 특히 한 가지 작업은 멤버십 수준 구매 또는 구독의 증거를 기반으로 사용자 수준 권한을 업데이트하는 것이었습니다. 회사에서 특정 회원 등급에 대한 사용자의 지불을 찾을 수 없는 경우 사용자의 멤버십 등급을 제거하기를 원했습니다. 이것이 왜 필요했습니까? 아마도 회원이 구독을 중단했지만 이벤트가 발생하지 않았으므로 회원은 비용을 지불하지 않아도 여전히 액세스할 수 있습니다(예!). 또는 누군가가 평가판 제안을 받았지만 해당 제안이 만료되었고 클라이언트는 여전히 구독을 보유하고 있습니다.

솔루션: 관리자 패널로 이동하여 수백(아마도 수천)개의 구독을 수동으로 삭제하는 대신 내가 좋아하는 WordPress 도구 중 하나인 WP-CLI를 선택하여 몇 번의 키 입력으로 문제를 해결했습니다.

이 게시물에서는 WP-CLI를 소개하고(이미 가까운 친구가 아니라고 가정), 이 특정 상황에 대해 작성한 간단한 사용자 지정 명령을 안내하고, WP-CLI를 사용하기 위한 몇 가지 아이디어와 리소스를 제공합니다. 자신의 발전.

WP-CLI란 무엇입니까?

이전에 WP-CLI에 대해 들어본 적이 없다면 혼자가 아닙니다. 이 프로젝트는 몇 년이 되었지만 한동안 WordPress 레이더 아래에 있는 것처럼 보였습니다. 다음은 공식 웹사이트에서 WP-CLI가 무엇이며 수행하는 작업에 대한 간략한 설명입니다.

WP-CLI는 WordPress 설치를 관리하기 위한 명령줄 도구 모음입니다. 웹 브라우저를 사용하지 않고도 플러그인 업데이트, 다중 사이트 설치 설정 등을 수행할 수 있습니다.

다음 명령은 즉시 사용 가능한 WP-CLI의 성능을 보여줍니다.

  • wp plugin update --all 업데이트 가능한 모든 플러그인을 업데이트합니다.
  • wp db export 는 데이터베이스의 SQL 덤프를 내보냅니다.
  • wp media regenerate 는 첨부 파일의 축소판을 재생성합니다(예: 테마에서 크기를 변경한 후).
  • wp checksum core 는 WordPress 코어 파일이 변조되지 않았는지 확인합니다.
  • wp search-replace 는 데이터베이스에서 문자열을 검색하고 바꿉니다.

여기에서 더 많은 명령을 탐색하면 모든 WordPress 개발자 또는 사이트 관리자가 매일 또는 매주 수행하는 반복 작업에 사용할 수 있는 명령이 많이 있음을 알 수 있습니다. 이러한 명령을 통해 나는 일년 내내 가리키고, 클릭하고, 페이지 새로고침을 기다리는 수많은 시간을 절약할 수 있었습니다.

당신은 확신합니까? 시작할 준비가 되셨습니까? 엄청난!

WordPress와 함께 WP-CLI가 설치되어 있어야 합니다(또는 로컬 컴퓨터에 전역적으로). 로컬 개발 환경에 WP-CLI를 아직 설치하지 않았다면 여기 웹사이트에서 설치 지침을 찾을 수 있습니다. VVV2(Varying Vagrant Vagrants)를 사용하는 경우 WP-CLI가 포함됩니다. 많은 호스팅 제공업체의 플랫폼에 WP-CLI도 포함되어 있습니다. 앞으로 성공적으로 설치했다고 가정합니다.

WP-CLI를 사용하여 문제 해결

반복적인 작업의 문제를 해결하려면 WordPress 설치에서 사용자 정의 WP-CLI 명령을 사용할 수 있도록 해야 합니다. 사이트에 기능을 추가하는 가장 쉬운 방법 중 하나는 플러그인을 만드는 것입니다. 세 가지 주요 이유로 이 인스턴스에서 플러그인을 사용합니다.

  1. 필요하지 않은 경우 사용자 지정 명령을 끌 수 있습니다.
  2. 모듈을 유지하면서 명령과 하위 명령을 쉽게 확장할 수 있습니다.
  3. 테마 및 다른 WordPress 설치에서도 기능을 유지할 수 있습니다.

플러그인 만들기

플러그인을 생성하려면 wp-content 디렉토리의 /plugins 디렉토리에 디렉토리를 추가해야 합니다. 이 디렉토리 toptal-wpcli 라고 부를 수 있습니다. 그런 다음 해당 디렉터리에 두 개의 파일을 만듭니다.

  • index.php , 한 줄의 코드만 있어야 합니다. <?php // Silence is golden .
  • plugin.php , 코드가 들어갈 위치입니다(이 파일의 이름은 원하는 대로 지정할 수 있습니다.)

plugin.php 파일을 열고 다음 코드를 추가하십시오.

 <?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; }

이 처음 몇 줄에는 두 부분이 있습니다.

먼저 플러그인 헤더가 있습니다. 이 정보는 WordPress 플러그인 관리 페이지로 가져와 플러그인을 등록하고 활성화할 수 있습니다. 플러그인 이름만 필요하지만 이 코드를 사용하려는 사람(그리고 미래의 자신도!)을 위해 나머지를 포함해야 합니다.

둘째, WP-CLI가 정의되어 있는지 확인합니다. 즉, WP-CLI 상수가 있는지 확인합니다. 그렇지 않은 경우 플러그인을 실행하지 않고 보류하려고 합니다. 존재하는 경우 나머지 코드를 실행하는 것이 좋습니다.

이 두 섹션 사이에 이 코드를 프로덕션에서 "있는 그대로" 사용해서는 안 된다는 메모를 추가했습니다. 일부 기능은 실제 기능의 자리 표시자이기 때문입니다. 이러한 자리 표시자 기능을 실제 활성 기능으로 변경하는 경우 이 메모를 자유롭게 삭제하십시오.

사용자 지정 명령 추가

다음으로 다음 코드를 포함하려고 합니다.

 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' );

이 코드 블록은 다음 두 가지 작업을 수행합니다.

  1. 이는 인수를 전달할 수 있는 TOPTAL_WP_CLI_COMMANDS 클래스를 정의합니다.
  2. toptal 명령을 클래스에 할당하므로 명령줄에서 실행할 수 있습니다.

이제 wp toptal remove_user 를 실행하면 다음이 표시됩니다.

 $ wp toptal hello hello world

이것은 toptal 명령이 등록되었고 하위 명령 remove_user 가 작동 중임을 의미합니다.

변수 설정

사용자 제거를 일괄 처리하므로 다음 변수를 설정하려고 합니다.

 // 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'] );

각 변수의 의도는 다음과 같습니다.

  • total_warnings : 이메일이 존재하지 않거나 이메일이 제거할 멤버십 등급과 연결되어 있지 않은 경우 경고를 집계합니다.
  • $total_users_removed : 프로세스에서 제거된 사용자 수를 집계하려고 합니다(아래 주의 사항 참조).
  • $dry_suffix : 테스트 실행인 경우 최종 성공 알림에 문구를 추가하려고 합니다.
  • $emails_not_existing : 존재하지 않는 이메일 목록을 저장합니다.
  • $emails_without_level : 지정된 레벨이 없는 이메일 목록을 저장합니다.
  • $dry_run : 스크립트가 테스트 실행을 하는지(true) 아닌지(false) 저장하는 부울.
  • $level : 확인하고 제거할 수준을 나타내는 정수입니다.
  • $email : 주어진 레벨에 대해 확인할 이메일의 배열. 우리는 이 배열을 반복할 것입니다

변수가 설정되면 실제로 함수를 실행할 준비가 되었습니다. 진정한 WordPress 방식으로 루프를 실행합니다.

함수 자체 작성

$emails 배열의 모든 이메일을 순환하는 foreach 루프를 만드는 것으로 시작합니다.

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

그런 다음 조건부 검사를 추가합니다.

 // 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

이 확인을 통해 확인 중인 이메일에 등록된 사용자가 있는지 확인합니다. email_exists() 함수를 사용하여 해당 이메일을 가진 사용자가 있는지 확인합니다. 해당 이메일을 가진 사용자를 찾지 못하면 터미널 화면에서 이메일을 찾을 수 없다는 경고를 표시합니다.

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

그런 다음 이메일은 나중에 표시할 수 있도록 $emails_not_existing 배열에 저장됩니다. 그런 다음 총 경고를 1씩 증가시키고 루프를 통해 다음 이메일까지 계속합니다.

이메일이 존재하는 경우 $user_id$level 변수를 사용하여 사용자가 해당 수준에 액세스할 수 있는지 확인합니다. 결과 부울 값을 $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

이 예제의 대부분의 함수와 마찬가지로 이 function_to_check_membership_level() 함수는 조작되지만 대부분의 멤버십 플러그인에는 이 정보를 얻을 수 있는 도우미 함수가 있어야 합니다.

이제 우리는 주요 작업으로 넘어갈 것입니다: 사용자로부터 레벨을 제거합니다. 다음과 같은 if/else 구조를 사용합니다.

 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

$has_level 의 값이 "truthy"(사용자가 멤버십 수준에 액세스할 수 있음을 의미)인 경우 해당 수준을 제거하는 함수를 실행하려고 합니다. 이 예에서는 function_to_deactivate_membership_level() 함수를 사용하여 이 작업을 수행합니다.

그러나 실제로 사용자로부터 레벨을 제거하기 전에 조건부 검사에 해당 기능을 포함하여 이것이 실제로 dry-run 인지 확인하려고 합니다. 그렇다면 우리는 아무것도 제거하고 싶지 않고 우리가 제거했다고 보고만 하십시오. 테스트 dry-run 이 아닌 경우 사용자로부터 레벨을 제거하고 성공 메시지를 터미널에 기록하고 이메일을 계속 반복합니다.

반면에 $has_level 값이 "falsey"인 경우(사용자가 멤버십 수준에 액세스할 수 없음을 의미하는 경우) 터미널에 경고를 기록하고 이메일을 $emails_without_level 배열로 푸시하고 계속하기를 원합니다. 이메일을 반복합니다.

마무리 및 보고

루프가 완료되면 결과를 콘솔에 기록하려고 합니다. 테스트 실행인 경우 콘솔에 추가 메시지를 기록하려고 합니다.

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

$dry-suffix 는 다음에 기록할 경고 및 성공 알림에 추가됩니다.

끝으로 결과를 성공 메시지로 기록하고 경고를 경고 메시지로 기록하려고 합니다. 우리는 이렇게 할 것입니다:

 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 ); }

WP_CLI::successWP_CLI::warning 도우미 메서드를 사용하고 있습니다. 콘솔에 정보를 기록하기 위해 WP-CLI에서 제공합니다. $total_users_removed , $total_warnings$dry_suffix 변수를 포함하여 여기에서 수행하는 문자열을 쉽게 기록할 수 있습니다.

마지막으로 스크립트 실행 시간 동안 경고가 발생한 경우 해당 정보를 콘솔에 인쇄하려고 합니다. 조건부 검사를 실행한 후 $emails_not_existing$emails_without_level 배열 변수를 문자열 변수로 변환합니다. WP_CLI::warning 도우미 메서드를 사용하여 콘솔에 인쇄할 수 있도록 이 작업을 수행합니다.

설명 추가

우리 모두는 주석이 다른 사람들과 몇 주, 몇 달 또는 몇 년 후에 우리의 코드로 되돌아가는 우리의 미래 자신에게 도움이 된다는 것을 압니다. WP-CLI는 명령에 주석을 달 수 있는 간단한 설명(shortdesc)과 긴 설명(longdesc)의 인터페이스를 제공합니다. 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 */

longdesc에서 우리는 사용자 정의 명령이 수신할 것으로 예상하는 것을 정의합니다. shortdesc 및 longdesc의 구문은 Markdown Extra입니다. ## OPTIONS 섹션에서 수신할 것으로 예상되는 인수를 정의합니다. 인수가 필수인 경우 < > 로 래핑하고 선택 사항인 경우 [ ] 로 래핑합니다.

이러한 옵션은 명령이 실행될 때 유효성이 검사됩니다. 예를 들어 필수 이메일 매개변수를 생략하면 다음 오류가 발생합니다.

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

## EXAMPLES 섹션에는 호출될 때 명령이 어떻게 보일 수 있는지에 대한 예가 포함되어 있습니다.

이제 사용자 지정 명령이 완료되었습니다. 여기에서 최종 요지를 볼 수 있습니다.

주의 사항 및 개선의 여지

코드를 개선, 확장 및 리팩토링할 수 있는 방법을 보려면 여기에서 수행한 작업을 검토하는 것이 중요합니다. 이 스크립트에는 개선해야 할 부분이 많이 있습니다. 다음은 개선할 수 있는 몇 가지 관찰 사항입니다.

때때로 이 스크립트가 "제거됨"으로 기록된 모든 사용자를 제거하지 않는다는 것을 알았습니다. 이는 쿼리가 실행할 수 있는 것보다 빠르게 실행되는 스크립트 때문일 가능성이 큽니다. 스크립트가 실행되는 환경 및 설정에 따라 경험이 다를 수 있습니다. 이를 우회하는 빠른 방법은 동일한 입력으로 반복적으로 실행하는 것입니다. 결국에는 0이 되고 제거된 사용자가 없다고 보고합니다.

사용자를 실제로 제거된 것으로 기록하기 전에 사용자가 제거되었는지 확인하고 기다리도록 스크립트를 개선할 수 있습니다. 이렇게 하면 스크립트 실행이 느려지지만 더 정확하고 한 번만 실행하면 됩니다.

유사하게, 이와 같은 오류가 발견된 경우 스크립트는 사용자로부터 레벨이 제거되지 않았음을 경고하는 오류를 발생시킬 수 있습니다.

스크립트를 개선하기 위한 또 다른 영역은 하나의 이메일 주소에서 한 번에 여러 수준을 제거할 수 있도록 하는 것입니다. 스크립트는 하나 이상의 레벨과 제거할 하나 이상의 이메일이 있는지 자동 감지할 수 있습니다. 레벨별로 CSV 파일을 받았기 때문에 한 번에 한 레벨만 실행하면 되었습니다.

또한 현재 가지고 있는 보다 장황한 조건부 검사 대신 삼항 연산자를 사용하도록 일부 코드를 리팩토링할 수 있습니다. 나는 데모를 위해 이것을 더 읽기 쉽게 만들기로 선택했지만 자유롭게 코드를 자신의 것으로 만들 수 있습니다.

마지막 단계에서 이메일을 콘솔로 인쇄하는 대신 이메일을 CSV 또는 일반 텍스트 파일로 자동으로 내보낼 수도 있습니다.

마지막으로 $level 변수에 대한 정수 또는 $emails 변수에 이메일 또는 쉼표로 구분된 이메일 목록을 가져오는지 확인하는 검사가 없습니다. 현재 누군가가 정수 대신 문자열을 포함하거나 이메일 대신 사용자 로그인 이름을 포함하면 스크립트가 작동하지 않고 오류가 발생하지 않습니다. 정수 및 이메일 검사를 추가할 수 있습니다.

추가 자동화 및 추가 읽기를 위한 아이디어

보시다시피, 이 특정 사용 사례에서도 WP-CLI는 작업을 빠르고 효율적으로 완료하는 데 도움이 될 만큼 충분히 유연하고 강력합니다. "일일 및 주간 개발 흐름에서 WP-CLI 구현을 시작하려면 어떻게 해야 하나요?"

WP-CLI를 사용할 수 있는 방법에는 여러 가지가 있습니다. 다음은 내가 좋아하는 몇 가지입니다.

  • 관리자 패널로 이동할 필요 없이 테마, 플러그인 및 WP 코어를 업데이트하십시오.
  • 백업을 위해 데이터베이스를 내보내거나 SQL 쿼리를 테스트하려는 경우 빠른 SQL 덤프를 수행합니다.
  • WordPress 사이트를 마이그레이션하십시오.
  • 더미 데이터 또는 사용자 정의 플러그인 제품군 설정으로 새로운 WordPress 사이트를 설치하십시오.
  • 코어 파일에 체크섬을 실행하여 손상되지 않았는지 확인합니다. (실제로 이것을 WP repo의 테마와 플러그인으로 확장하는 프로젝트가 진행 중입니다.)
  • 사이트 호스트를 확인, 업데이트 및 유지 관리하는 스크립트를 작성하십시오(여기에 대해 썼습니다).

WP-CLI의 가능성은 거의 무한합니다. 다음은 계속 발전할 수 있는 몇 가지 리소스입니다.

  • 주요 WP-CLI 사이트: http://wp-cli.org
  • WP-CLI 명령: https://developer.wordpress.org/cli/commands/
  • 공식 WP-CLI 블로그: https://make.wordpress.org/cli/
  • WP-CLI 핸드북: https://make.wordpress.org/cli/handbook/
  • WooCommerce로? WC-CLI 확인: https://github.com/woocommerce/woocommerce/wiki/WC-CLI-Overview#woocommerce-commands
  • 프로젝트 관리자인 Daniel Bachhuber와의 팟캐스트 인터뷰: https://howibuilt.it/episode-28-daniel-bachhuber-wp-cli/