不要重复自己(使用WP-CLI自动执行重复性任务)

本文概述

  • 什么是WP-CLI?
  • 使用WP-CLI解决问题
  • 注意事项和改进空间
  • 进一步自动化和进一步阅读的想法
你是否曾经发现自己进入WordPress管理区域以更新主题, 插件和WP核心?当然有是否问过你:” 你可以在此CSV文件中创建/更新/删除所有用户吗?” 我确定你也遇到了这种情况。你是否尝试过迁移网站, 并希望可以找到一个插件或第三方工具来完成这项工作?我知道我有!
不要重复自己(使用WP-CLI自动执行重复性任务)

文章图片
有一个非常强大的工具可以帮助你完成这些任务以及更多任务。在向你介绍之前, 我想先简单介绍一下。
问题:在最近的项目中, 我需要定期重复执行一些编程任务。其中一项任务特别涉及根据成员资格级别购买或订阅的证据来更新用户级别权限。如果公司找不到来自用户的特定会员级别的付款, 则他们希望从用户中删除会员级别。为什么需要这个?也许某个会员停止了订阅, 但是活动没有触发, 因此即使他们不付费也可以访问该会员(赞!)。或者, 也许有人在试用报价, 但该报价过期了, 客户仍然有订阅(也叫!)。
解决方案:我选择进入我最喜欢的WordPress工具之一WP-CLI, 而不是进入管理面板并手动删除数百个(也许是数千个)订阅, 它通过几次按键即可解决此问题。
在本文中, 我想向你介绍WP-CLI(假设你还不是亲密的朋友), 引导你完成针对这种特殊情况编写的简单自定义命令, 并为你提供一些在WP-CLI中使用WP-CLI的想法和资源。你自己的发展。
什么是WP-CLI? 如果你以前从未听说过WP-CLI, 那么你并不孤单。该项目虽然已有数年之久, 但似乎在WordPress的雷达下飞行了一段时间。以下是官方网站对WP-CLI的简要说明:
WP-CLI是一组用于管理WordPress安装的命令行工具。你可以在不使用网络浏览器的情况下更新插件, 设置多站点安装等等。
以下命令可立即显示WP-CLI的功能:
  • wp插件更新-全部更新所有可更新的插件。
  • wp db export导出数据库的SQL转储。
  • wp media regenerate重新生成附件的缩略图(例如, 在更改主题大小后)。
  • wp checksum core验证WordPress核心文件是否未被篡改。
  • wp search-replace搜索并替换数据库中的字符串。
如果你在此处浏览更多命令, 你将看到每个WordPress开发人员或网站维护人员每天或每周都会执行许多重复性任务的可用命令。这些命令在一年中为我节省了无数的指向, 单击和等待页面重新加载的时间。
你说服了吗?准备开始了吗?大!
你将需要在WordPress上安装WP-CLI(或在本地计算机上全局安装)。如果尚未在本地开发环境上安装WP-CLI, 则可在此处的网站上找到安装说明。如果你使用的是多种多样的无业游民(VVV2), 则包含WP-CLI。许多托管服务提供商在其平台上还包含WP-CLI。我将假设你已经成功安装了此产品。
使用WP-CLI解决问题 为了解决重复任务的问题, 我们需要使自定义WP-CLI命令可用于我们的WordPress安装。向任何站点添加功能的最简单方法之一就是创建一个插件。我们将在此实例中使用插件的原因主要有以下三个:
  1. 如果不需要, 我们将能够关闭自定义命令
  2. 我们可以轻松扩展所有命令和子命令, 同时保持模块化。
  3. 我们可以维护跨主题甚至其他WordPress安装的功能。
创建插件
要创建插件, 我们需要在wp-content目录中的/ plugins目录中添加目录。我们可以将此目录称为srcmini-wpcli。然后在该目录中创建两个文件:
  • index.php, 应该只包含一行代码:< ?php //沉默是金色的
  • plugin.php, 这是我们的代码所在的位置(你可以根据需要命名此文件。)
打开plugin.php文件并添加以下代码:
< ?php /** * Plugin Name: srcmini 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: srcmini-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 srcmini_WP_CLI_COMMANDS extends WP_CLI_Command { function remove_user() {echo "\n\n hello world \n\n"; }}WP_CLI::add_command( 'srcmini', 'srcmini_WP_CLI_COMMANDS' );

此代码块为我们做两件事:
  1. 它定义了srcmini_WP_CLI_COMMANDS类, 我们可以将参数传递给该类。
  2. 它将命令srcmini分配给该类, 因此我们可以从命令行运行它。
现在, 如果执行wp srcmini remove_user, 我们将看到:
$ wp srcmini hello hello world

这意味着我们的命令srcmini已注册, 子命令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:一个布尔值, 用于存储脚本是否在进行试运行(真)或否(假)。
  • $ level:一个整数, 表示要检查并可能删除的级别。
  • $ email:检查给定级别的电子邮件数组。我们将遍历此数组
设置好变量后, 我们就可以实际运行该函数了。以真正的WordPress方式, 我们将运行一个循环。
自己编写函数
我们首先创建一个foreach循环来循环遍历$ emails数组中的所有电子邮件:
// 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 srcmini remove_user [email  protected] --dry-runWarning: The user [email  protected] does not seem to exist.

然后, 电子邮件将存储在$ emails_not_existing数组中, 以便以后显示。然后, 我们将警告总数增加一, 并继续循环到下一封电子邮件。
如果电子邮件确实存在, 我们将使用$ 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()函数是伪造的, 但大多数成员资格插件应具有帮助程序函数以获取此信息。
【不要重复自己(使用WP-CLI自动执行重复性任务)】现在, 我们继续进行主要操作:从用户中删除关卡。我们将使用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()函数执行此操作。
但是, 在我们实际从用户删除级别之前, 我们希望将该功能包含在条件检查中, 以查看这是否实际上是试运行。如果是这样, 我们不希望删除任何内容, 仅报告我们所做的。如果不是空运行, 那么我们将继续进行操作, 并从用户那里删除级别, 将成功消息记录到终端, 然后继续遍历电子邮件。
另一方面, 如果$ has_level的值为” falsey” , 则意味着用户无权访问会员级别, 我们希望向终端记录警告, 将电子邮件推送到$ emails_without_level数组, 然后继续遍历电子邮件。
整理和报告
循环完成后, 我们希望将结果记录到控制台。如果这是一次试运行, 我们想向控制台记录一条额外的消息:
if ( $dry_run ) { $dry_suffix = 'BUT, nothing really changed because this was a dry run:-).'; }

该$ dry后缀将附加到我们接下来记录的警告和成功通知中。
最后, 我们希望将结果记录为成功消息, 将警告记录为警告消息。我们将这样做:
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 :: success和WP_CLI :: warning helper方法。这些由WP-CLI提供, 用于将信息记录到控制台。你可以轻松地记录字符串, 这是我们在这里所做的, 包括$ total_users_removed, $ total_warnings和$ dry_suffix变量。
最后, 如果我们在脚本的整个运行过程中确实产生了任何警告, 则希望将该信息打印到控制台。运行条件检查后, 我们将$ emails_not_existing和$ emails_without_level数组变量转换为字符串变量。我们这样做是为了可以使用WP_CLI :: warning helper方法将它们打印到控制台。
添加描述
我们都知道注释对其他人和对我们自己的未来都有帮助, 这些注释可以追溯到数周, 数月甚至数年后的代码中。 WP-CLI提供了简短描述(shortdesc)和长描述(longdesc)的接口, 使我们可以注释命令。在定义srcmini_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 srcmini remove_user --level=5 [email  protected], [email  protected], [email  protected] --dry-run * * @when after_wp_load */

在longdesc中, 我们定义了自定义命令希望接收的内容。 shortdesc和longdesc的语法是Markdown Extra。在## OPTIONS部分下, 我们定义了我们希望接收的参数。如果需要参数, 则将其包装在< > 中;如果参数是可选的, 则将其包装在[]中。
运行命令时, 将验证这些选项。例如, 如果我们省略了必需的email参数, 则会出现以下错误:
$ wp srcmini remove_user --level=5 --dry-run Error: Parameter errors: missing --email parameter (Email of user to check against)

” ##示例” 部分包含一个示例, 说明该命令在被调用时的外观。
我们的自定义命令现已完成。你可以在此处查看最终要点。
注意事项和改进空间 回顾我们在这里所做的工作很重要, 以查看如何改进, 扩展和重构代码。此脚本有很多改进之处。以下是有关可以改进的一些观察结果。
有时, 我发现此脚本不会删除它记录为” 已删除” 的所有用户。这很可能是由于脚本运行速度比查询执行速度快。你的经验可能会有所不同, 具体取决于运行脚本的环境和设置。解决此问题的快速方法是使用相同的输入重复运行。最终将归零, 并报告尚未删除任何用户。
可以对脚本进行改进, 以等待并验证是否已删除用户, 然后再将用户实际记录为已删除。这会减慢脚本的执行速度, 但会更加准确, 你只需运行一次即可。
同样, 如果发现这样的错误, 脚本可能会抛出错误, 以警告尚未从用户删除级别。
改进脚本的另一个方面是允许一次从一个电子邮件地址中删除多个级别。该脚本可以自动检测是否存在一个或多个级别以及要删除的一封或多封电子邮件。按级别为我提供了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/

    推荐阅读