个性化阅读
专注于IT技术分析

你的WordPress API开发人员未使用的五种经过久经考验的技术

本文概述

至少在客户眼中, 提升你作为WordPress开发人员的地位的最佳方法之一就是变得熟练使用API​​。这是实现WordPress API的常见方案:客户要求你向其网站添加小部件, 例如电子邮件订阅小部件。你可以从其第三方电子邮件服务中获取一些代码(可能是脚本标签或iframe), 然后将其粘贴到页面中, 然后回复客户”知道了!”

不幸的是, 你正在与要求更高的客户打交道, 他们注意到以下缺陷:

  • 尽管该窗口小部件与网站的其余部分一样都使用无衬线字体, 但它并不是正确的字体。该小部件使用的是Helvetica, 而不是你安装的自定义字体。
  • 小部件的订阅表单会触发新的页面加载, 如果将其放置在文章的中间, 则会造成破坏。
  • 在页面的其余部分之后, 该窗口小部件似乎需要花费额外的时间来加载, 这感觉既刺耳又便宜。
  • 客户端希望基于订阅者发布的帖子为其元数据标记订阅者, 并且该小部件不提供与该功能类似的远程功能。
  • 客户感到烦恼的是, 他们现在必须管理两个仪表板(wp-admin和电子邮件服务的管理区域)。

此时, 可能会发生以下两种情况之一。你可以将这些项目声明为”必备”, 并向客户保证80/20解决方案的优点, 或者你可以兑现这些要求。以我的亲身经历, 我发现完成此类请求(即表明他们掌握了第三方服务)是一种可靠的方式, 可以说服客户你是WordPress向导。另外, 这样做通常很有趣。

在过去的十年中, 我已经将WordPress用作针对50种不同API进行API消费的平台。一些最常见的API是MailChimp, Google Analytics, Google Maps, CloudFlare和Bitbucket。但是, 如果你需要做更多的事情, 又需要自定义解决方案怎么办?

如何开发WordPress API客户端

在本文中, 我将针对通用的”电子邮件服务” API进行开发, 尽我所能使事情尽可能地不可知。但是, 我确实认为假设我们正在处理JSON REST API是合理的。以下是一些背景主题, 可以帮助你享受本文中的技术要点:

  • WordPress HTTP系列功能
  • JSON
  • 休息

如果你发现自己对这些主题不太熟悉, 并且对深入研究感兴趣, 请立即暂停并下载出色的Postman应用程序。它使你无需编写代码即可与API通信。

Postman仪表板的屏幕截图

邮差。也许是我最喜欢的开发工具?

但是, 如果你完全不熟悉这些内容, 请继续阅读。具有一定程度的WordPress经验的技术读者可以从本文中获得最大收益, 但是我会以一种技术性较低的方式来解释每种技术的价值。非技术读者将使本文能够在赞助每个点之前评估其投资回报率, 并在交付后判断实施质量。

注意:如果你需要快速进修课程, 可以查看我们的WordPress REST API指南。

没有更多的序言, 请允许我与你分享一些不同的技术, 这些技术对我工作的每个API, 项目和团队都很赞赏。

瞬态:何时握住它们, 何时折叠它们

在我的开始段落中, 我注意到客户发现横跨两个管理区域很烦人:wp-admin和电子邮件服务的仪表板。解决该问题的一个好方法是在wp-admin中为他们提供一个仪表板小部件, 以显示其最近订阅者活动的摘要。

wp-admin仪表板小部件的屏幕截图

我们可能在WordPress中提供的仪表板UI类型的示例, 以节省客户前往其第三方电子邮件服务提供商的行程。

但是话又说回来, 这可能需要多个HTTP请求到远程API(由电子邮件服务提供的API), 从而导致页面加载很长。解决此性能问题的方法是将API调用存储为瞬态。该Codex文章为你提供了一个绝妙的解释, 你绝对应该阅读其中的内容, 因此, 我将对其进行总结:

  1. 从远程API获取数据。
  2. 使用set_transient()将其存储, 并根据你自己对性能, 速率限制和在此特定应用程序中显示过时数据的错误余量的判断来选择到期时间。
  3. 继续你的业务逻辑-处理数据, 返回值, 无论何种情况。
  4. 当你再次需要数据时(例如在下一页加载时), 请在使用你需要从API获取数据之前, 使用get_transient()在瞬态缓存中检查数据。

我认为这是一个有用且可行的基础, 但是如果你想一想一下REST动词, 则可以更进一步。在最常用的五种方法(GET, POST, PATCH, PUT, DELETE)中, 只有一种属于你的瞬时缓存。你能猜出哪一个吗?是GET。在我的插件中, 几乎总是有一个PHP类专用于抽象对所涉及的远程API的调用, 实例化该类时的参数是HTTP方法。如果不是GET调用, 那么我根本不会调用任何缓存层。

此外, 如果不是GET通话, 则可以认为我正在采取某种措施以某种方式更改远程数据, 例如通过添加, 编辑或删除电子邮件订户。这可能是通过delete_transient()使该资源的现有缓存无效的好时机。

返回我们的WordPress电子邮件订阅API的示例, 以下是实际的工作方式:

  • 用于显示最近订阅者的仪表板小部件将通过GET请求为/ subscribers调用API端点。由于是GET请求, 因此将其存储在我的临时缓存中。
  • 用于订阅电子邮件列表的侧边栏小部件将通过POST请求为/ subscribers调用API端点。因为这是一个POST请求, 所以不仅会避免我的临时缓存, 还会激怒我删除我的临时缓存的相关部分, 以便仪表板小部件反映此新订阅者。
  • 在命名瞬态时, 我经常通过在我要调用的远程API URL之后实际地命名它们来组织它们。这是一种识别要删除的正确瞬变的便捷方法。如果它是接受参数的端点, 则将它们连接成一个字符串, 并将它们也添加到临时名称中。

作为客户或其他技术含量较低的利益相关者, 无论何时应用程序从远程服务中提取数据, 你都应特别要求进行瞬时缓存(至少是讨论)。你应该熟悉出色的Query Monitor插件, 以了解瞬态如何工作。它将为你提供一个界面, 用于浏览将哪些数据存储为暂态数据, 存储频率和存储时间。

有时瞬变不够好

某些高级WordPress托管服务实际上不允许你在生产中使用瞬态。它们以MU插件或其他脚本的形式运行代码, 这些代码将拦截你尝试使用暂态API的尝试, 并通过对象缓存存储该信息。 WP-Engine最常见的配置就是一个很好的例子。

标题中描述的phpMyAdmin视图的屏幕截图

phpMyAdmin UI中令人震惊的景象:生产站点完全没有瞬态现象?这可能意味着对象缓存正在起作用。

如果你只是存储和检索数据, 则实际上不必关心它, 甚至可能永远不会注意到它的发生。 * _transient()函数的整个系列将为你提供相同的最终结果, 只是对其进行了过滤以使用对象缓存而不是瞬时缓存。但是, 尝试删除瞬变时可能会遇到问题。这就是为什么。

如果你的API集成足够复杂, 可以使用其自己的设置页面, 则不妨包括一个UI, 以允许管理员用户清除插件的整个临时缓存。此按钮最常见的用法是, 当客户端直接在远程服务上更改某些数据, 并且想要使我们存储在WordPress中的缓存无效时。如果客户端更改帐户凭据, API密钥, 或者通常仅作为调试的”出厂重置”按钮, 则此按钮也可能会派上用场。

选项按钮的屏幕截图

允许客户端清空其API数据的本地缓存的UI的示例。

即使你足够聪明地为所有临时键命名空间, 以便你有希望为delete_transient()标识每个临时键, 但最理想的情况仍可能涉及原始SQL, 我一直试图在WordPress中避免这种情况:

<?php
// Purge all the transients associated with our plugin.
function purge() {
  global $wpdb;
  $prefix = esc_sql( $this -> get_transient_prefix() );
  $options = $wpdb -> options;
  $t  = esc_sql( "_transient_timeout_$prefix%" );
  $sql = $wpdb -> prepare (
    "
      SELECT option_name
      FROM $options
      WHERE option_name LIKE '%s'
    ", $t
  );
  $transients = $wpdb -> get_col( $sql );
  // For each transient...
  foreach( $transients as $transient ) {
    // Strip away the WordPress prefix in order to arrive at the transient key.
    $key = str_replace( '_transient_timeout_', '', $transient );
    // Now that we have the key, use WordPress core to the delete the transient.
    delete_transient( $key );
  }
  
}
?>

不方便, 效率不高。相反, 这种情况需要对象缓存, 因为对象缓存为我们提供了一种将缓存值分组在一起的便捷方法。这样, 当你需要清空与插件相关的所有缓存值时, 只需简单地调用wp_cache_delete($ key, $ group)。

总结一下, 我要说的是:如果你还不是管理该数据缓存的专家, 那么你就不能成为使用API​​的专家。

作为客户端, 需要注意的关键是过渡和生产环境之间的异常缓存行为。换句话说, 尽管在暂存阶段测试新一批工作始终是一个好习惯, 但是缓存也必须在生产中进行同样的仔细测试。

远程API可以帮助通知你的PHP类层次结构

在为插件布置各种PHP类时, 我经常发现模仿API端点的定义方式很有帮助-例如, 以下端点似乎有什么共同点?

  • https://api.example-email-service.com/v1/subscribers.json
  • https://api.example-email-service.com/v1/lists.json
  • https://api.example-email-service.com/v1/campaigns.json

它们都返回集合, 我的意思是GET请求的结果, 返回零对多的结果, 其中每个结果都是数组的成员。这听起来似乎很明显, 但是我发现它对我的PHP代码中的以下类结构很有帮助:

  • class.collection.php, 一个抽象类
  • class.subscribers.php扩展了抽象类Collection。
  • class.lists.php扩展了抽象类Collection。
  • class.campaigns.php扩展了抽象类Collection。

抽象类将唯一的查询参数数组作为参数:分页, 排序列, 排序顺序和搜索过滤器之类的东西。它将具有用于执行常见任务的方法, 例如调用远程API, 处理错误, 以及将结果转换为HTML <select>菜单或jQueryUI AutoSuggest。实例化抽象类的类可能很短, 也许只需要指定要在* .json API端点URL中使用的字符串即可。

Mailchimp API操场的屏幕截图

Mailchimp发布了用于沙箱API调用等的API”游乐场”。它还是浏览其API的整个数据层次结构的便捷方式, 使我们对如何构造自己的类层次结构有一个有益的了解。

同样, 以下端点有什么共同点?

  • https://api.example-email-service.com/v1/subscribers/104abyh4.json
  • https://api.example-email-service.com/v1/lists/837dy1h2.json
  • https://api.example-email-service.com/v1/campaigns/9i8udr43.json

他们都返回一个项目, 我所说的恰好是集合中一个特定的, 唯一的成员:诸如一个特定的电子邮件订阅者, 一个电子邮件列表或一个电子邮件活动之类的东西。因此, 我喜欢在我的PHP代码中使用以下结构:

  • class.item.php, 一个抽象类
  • class.subscriber.php扩展了抽象类Item。
  • class.list.php扩展了抽象类Item。
  • class.campaign.php扩展了抽象类Item。

抽象类将以字符串作为唯一参数, 以标识所请求的特定项目。再次说明, 实例化的类可能很短, 也许仅比在* / duy736td.json中指定要使用的字符串做更多的事情。

构建类继承的方法有很多, 但是即使你对上面概述的方法采取了不同的方法, 我敢打赌, 远程API的结构很有可能会帮助你通知应用程序的结构。

作为客户端, 糟糕的体系结构的一个常见症状是当你发现自己不得不在整个应用程序中一遍又一遍地请求相同的更改时。例如, 如果你要求报告每页返回100个结果而不是10个结果, 并且你必须对订户报告, 活动报告, 退订报告等重复进行此请求, 则可能是在检测不良的类体系结构。在这种情况下, 值得询问你的团队是否将从重构周期中受益:这是一个工作目标, 其目标不是更改产品的行为, 而是改善基础代码, 从而使更改行为变得更加容易产品的未来。

WP_Error的完美用例

我很尴尬地承认, 我花了比实际开始在代码中正确使用WP_Error系列函数所花费的时间长的时间。我倾向于只编写自己的代码, 或者假设永远不会有值得通过程序解决的错误, 或者逐案处理它们。使用远程API就像激光束一样贯穿了这种思路, 因为它为使用WP_Error提供了极为方便和强大的用例。

回想一下, 我曾提到我经常有一个PHP类, 其目的是向远程API发出HTTP请求。当你剥离所有样板, 所有数据操作, 所有次要问题时, 该类实际上归结为调用wp_remote_request()以便从API获取HTTP响应对象。方便地, 如果调用由于某种原因而无法执行, 则wp_remote_request()会返回WP_Error, 但是如果调用成功返回了不利类型的HTTP响应, 该怎么办?

订阅表单的屏幕截图

从技术上讲, API调用是可行的, 但并非完全没有警告。需要在整个代码库中以一致的方式捕获并报告这些警告。

例如, 也许我们调用了/lists.json端点, 但是此特定帐户尚未设置任何列表。这将返回一个有效的HTTP响应, 但状态码为400。虽然这本身并不是致命错误, 但从某些前端代码的角度来看, 该代码希望将此API调用转换为下拉菜单, 但400以及成为WSOD!因此, 我发现对wp_remote_request()的结果进行一些额外的解析很有帮助, 毕竟可能返回WP_Error:

<?php
	function call() {
	
		$response       = wp_remote_request( $this -> url, $this -> args );
		$code           = wp_remote_retrieve_response_code( $response );
		$first_digit    = $code[0];
		$good_responses = array( 2, 3 ); 
		if( ! in_array( $first_digit, $good_responses ) {
			$body = wp_remote_retrieve_body( $response );
			$out  = new WP_Error( $code, $body );
		} else {
			$out = $response;
		}
		   
		return $out;
	
	}
?>

这种模式可以帮助简化调用调用者类的代码, 因为我们知道在继续输出之前可以安全地依赖is_wp_error()。

作为客户端, 你偶尔应该扮演恶意用户, 混乱用户和急躁用户的角色。以不应该使用的方式使用应用程序。做你的开发人员似乎不希望你做的事情。注意会发生什么。你收到有用的错误消息吗?你是否收到任何错误消息?如果不是这样, 可能值得赞助围绕更好的错误处理的工作。

ob_get_clean()的强大调试功能

现代的可编程网络, 几乎每个站点都使用其他站点的API, 并且本身通过自己的API进行使用, 已经成为一个功能强大的代码舞台。但是正是这种品质也会使它变得很慢。

在给定页面加载中, 远程HTTP请求通常是最耗时的部分。因此, 许多API驱动的组件都可以通过Ajax或cron执行。例如, 一个自动搜索电子邮件订阅者列表的建议可能应该在每次击键时按需ping通远程数据源, 而不是在页面加载时将DOM中的所有100, 000个订阅者加载。如果不是这种选择, 那么也许一个大型查询可以在每晚的cron任务上进行同步, 以便可以从本地镜像而不是远程API提取结果。

这种方法的问题在于可能难以调试。你不只是打开WP_DEBUG并让错误消息进入浏览器窗口, 还停留在浏览器网络控制台中, 或者在执行cron任务时(希望执行)尾随日志文件。我觉得这不舒服。

改善这种情况的一种方法是对error_log()进行仔细的策略调用。但是再一次, 日志记录的一个普遍问题是, 对于大型或繁忙的应用程序, 错误日志可能会变得太大或增长得太快, 从而无法用于监视或解析。因此, 我们必须对所记录的内容保持选择性, 并像对实际应用程序逻辑所做的那样多考虑。遗憾的是, 花了一些时间记录一些奇特的边缘案例错误, 这些错误似乎只是间歇性地在一些不常见的cron任务上发生, 而只是意识到该错误的真实性质再次使你回避了, 因为你未能记录某些特定的数组成员例如, 冒犯性价值。

因此, 我的理念已经变成, 我并不总是记录日志, 但是当我这样做时, 我便记录了所有内容。换句话说, 在确定了一个特别令人担忧的功能之后, 我将使用尽可能广泛的网络对其进行记录:

<?php
function debug( $bug ) {
	ob_start();
	var_dump( $bug );
	$out = ob_get_clean();
	error_log( $out );
}
?>

这相当于var_dump()将整个越野车值放入错误日志文件中的单个条目中。

错误日志文件的屏幕截图

错误日志太大了, 无法进行调试。

作为客户端, 值得定期检查你的应用程序的总文件内存使用情况。如果你发现自己突然违反了托管帐户中的存储限制, 则很可能会导致错误日志泛滥。你的开发人员将受益于专注于更好的日志记录的工作周期-你的客户也将受益!

并非完全是Clickbait, 但可以

请原谅本文的目录结构。由于这些模式非常通用, 因此我无法强迫这些观点成为统一的文章主题:它们适用于任何JSON REST端点和任何WordPress输出。

无论远程API是什么, 或者我们在WordPress中使用了什么远程API, 我都会一遍又一遍地看到它们。我已经尽力将所有这些原理收集到一个插件样板中, 从而极大地加快了我的工作。你是否为每个项目保留相似的观点?请分享它们, 以便我可以窃取它们并将其添加到我的样板中!

相关:如何进行现代WordPress开发(第1部分)

赞(0)
未经允许不得转载:srcmini » 你的WordPress API开发人员未使用的五种经过久经考验的技术

评论 抢沙发

评论前必须登录!