作者都是各自领域经过审查的专家,并撰写他们有经验的主题. All of our content is peer reviewed and validated by Toptal experts in the same field.
Scott写过数百个WordPress主题和插件. He specializes in third-party API integration and he’s an active tech writer.
提升你的地位的最好方法之一 WordPress developer, 至少在你的客户眼中是这样, is to become skilled at consuming APIs. 这里有一个实现WordPress API的常见场景:你的客户要求你向他们的站点添加一个小部件, for example, an email subscription widget. You grab some code from their third-party email service—perhaps it’s a script tag or an iframe
-将其粘贴到页面中,然后回复客户:“明白了!”
Unfortunately, 如果你面对的是一个要求更高的客户,他们会注意到你的以下缺点:
在这一点上,两件事之一可能会合理地发生. You could declare these items “nice-to-haves” and reassure your client about the merits of an 80/20 solution,或者你可以满足这些要求. In my personal experience, 我发现满足这样的要求——就是说, 展示对第三方服务的精通——是让客户相信你是一个WordPress向导的可靠方法. Plus, it’s often fun to do.
Over the past decade, I’ve used WordPress as a platform for API consumption against probably 50 different APIs. 一些最常见的api是MailChimp, Google Analytics, Google Maps, CloudFlare, and Bitbucket. 但如果你需要做更多,如果你需要一个定制的解决方案?
In this article, 我将针对通用的“电子邮件服务”API进行开发, 我尽我所能让事情变得尽可能的不可知论. However, I do feel it’s reasonable to assume that we’re dealing with a JSON REST API. Here are some background topics which might help you enjoy the technical points in this article:
If you find yourself marginally familiar with these topics and are interested in digging deeper, 现在暂停并下载优秀的 Postman application. 它允许您在不编写代码的情况下与api通信.
但是,如果你对这些不熟悉,请继续阅读. 具有一定程度WordPress经验的技术观众将从本文中获益最多, 但我会尽力解释的 value 以一种不那么专业的方式来介绍每种技术. 非技术读者离开本文时,将能够在赞助本文之前评估每个点的ROI,并在交付后判断实现的质量.
Note: 如果您需要快速复习课程,您可以查看我们的 WordPress REST API guide.
With no further preamble, 请允许我与您分享一些不同的技术,我发现自己对大多数API都很欣赏, project, and team with which I work.
In my opening paragraph, 我注意到,客户发现跨越两个管理区域很烦人:wp-admin和他们的电子邮件服务的仪表板. A good way to resolve that would be to provide them with a dashboard widget in wp-admin, 显示他们最近的订阅者活动摘要.
But then again, 这可能需要向远程API(由电子邮件服务提供的API)发出多个HTTP请求。, resulting in long page loads. The solution to this performance problem is to store API calls as transients. This Codex article provides a great explanation that you should definitely read, but I’ll summarize it thusly:
set_transient()
with an expiration time of your choosing based on your own judgement about performance, rate limits, and the margin for error in displaying outdated data in this particular application.get_transient()
然后得出结论,您需要从API获取它.我认为这是一个有益的和可行的基础, but you can take it a step further if you think for a moment about REST verbs. 在五个最常见的方法中(GET, POST, PATCH, PUT, DELETE), 其中只有一个属于你的临时缓存. Can you guess which one? It’s GET. In my plugins, I almost always have a PHP class dedicated to abstracting calls to the remote API in question, 实例化该类时的参数是HTTP方法. If it’s not a GET call, then I’m not going to invoke any caching layer at all.
Furthermore, if it’s not a GET call, then it stands to reason that I am taking some action to alter the remote data in some way, perhaps by adding, editing, or removing an email subscriber. This might be a good time to invalidate the existing cache for that resource, via delete_transient()
.
回到我们的WordPress邮件订阅API的例子, 以下是它在实践中的工作方式:
/subscribers
via a GET request. 因为它是一个GET请求,所以它被存储在我的临时缓存中./subscribers
via a POST request. Because it’s a POST request, 它不仅会避开我的暂存缓存, 这会促使我删除临时缓存的相关部分, 以便仪表板小部件反映这个新的订阅者.作为客户或其他技术含量较低的利益相关者, 在应用程序从远程服务提取数据的任何时候,都应该专门请求临时缓存——或者至少讨论一下. 你应该熟悉优秀的人 Query Monitor 插件来查看瞬态是如何工作的. It will give you an interface for browsing what data is being stashed as a transient, how frequently, and for how long.
一些高级WordPress托管服务实际上不允许你在生产环境中使用瞬态. They have code running, 也许以MU插件或其他脚本的形式, that will intercept your attempt to use the transients API and store that information via the object cache instead. WP-Engine,在其最常见的配置中,是这方面的一个主要例子.
如果您只是存储和检索数据, you actually don’t have to care about this and may never even notice it’s happening. The entire family of *_transient()
函数将为您提供相同的最终结果, 只是过滤使用对象缓存而不是临时缓存. Where you might run into problems, though, is when attempting to delete transients. Here’s why.
如果您的API集成足够复杂,需要自己的设置页面, 您可能希望包含一个UI,以允许管理用户执行以下操作 清除插件的整个临时缓存. 此按钮最常见的用途是当客户端直接更改远程服务上的一些数据时, 并且想要使我们存储在WordPress中的缓存失效. This button might also come in handy if the client changes account credentials, API keys, 或者只是作为调试的“出厂重置”按钮.
即使您足够聪明,可以为所有的瞬态键命名空间,这样您就有希望识别它们中的每一个 delete_transient()
,最好的情况可能仍然涉及原始SQL,这是我在WordPress中总是尽量避免的:
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 ($transient作为$transient) {
//去掉WordPress前缀,以便到达临时键.
$key = str_replace('_transient_timeout_', ', $transient ');
// Now that we have the key, use WordPress core to the delete the transient.
delete_transient( $key );
}
}
?>
Not convenient, not efficient. 相反,这种情况需要对象缓存 because object caching gives us a convenient way to group cached values together. This way, 当您需要清空与插件相关的所有缓存值时, it’s a simple one-liner call to wp_cache_delete( $key, $group )
.
我可以这样总结: 如果还不擅长管理数据的缓存,就不可能成为使用api的专家.
As a client, 需要注意的关键是在登台环境和生产环境之间异常的缓存行为. In other words, 尽管在暂存阶段测试新一批工作始终是一种很好的做法, caching is something that must also be tested in production with equal care.
在为我的插件布置各种PHP类时, I often find it helpful to mimic the way the API endpoints are defined—for example, 以下端点似乎有什么共同之处?
They all return collections, 我指的是GET请求的结果, 返回0到多的结果,其中每个结果都是数组的一个成员. That might sound fairly obvious, but I find it to be a helpful prompt for the following class structure in my PHP code:
class.collection.php
, an abstract classclass.subscribers.php
extends the abstract class, Collection
.class.lists.php
extends the abstract class, Collection
.class.campaigns.php
extends the abstract class, Collection
.抽象类将把查询参数数组作为它的唯一参数:分页之类的东西, sort column, sort order, and search filters. 它将具有用于调用远程API等常见任务的方法, handling errors, 并可能将结果转化为HTML menu or a jQueryUI AutoSuggest. 实例化抽象类的类可能非常短, 可能只是指定要在。中使用的字符串而已
*.json
API endpoint URL.
类似地,以下端点有什么共同之处?
They all return an item, 我指的是一个具体的, 集合中的唯一成员:比如一个特定的电子邮件订阅者, one email list, or one email campaign. 因此,我喜欢在我的PHP代码中使用以下结构:
class.item.php
, an abstract classclass.subscriber.php
extends the abstract class, Item
.class.list.php
extends the abstract class, Item
.class.campaign.php
extends the abstract class, Item
.抽象类的唯一参数是一个字符串,用于标识所请求的特定项. Once again, 被实例化的类可能非常短, 可能只是指定要使用的字符串 */duy736td.json
.
有许多方法可以构造类继承, 但即使你采取了我上面概述的不同方法, 我敢打赌,远程API的结构很有可能有助于了解应用程序的结构.
As a client, 糟糕架构的一个常见症状是,您发现自己不得不在整个应用程序中反复请求相同的更改. For example, 如果您请求报告每页返回100个结果,而不是10个, 你必须不断重复请求用户报告, campaign reports, unsubscribe reports, etc, 您可能会检测到糟糕的类体系结构. In this situation, 问一问你的团队,他们是否能从重构周期中获益是值得的:重构周期是一组工作,其目标不是改变产品的行为,而是改进底层代码,以便将来更容易改变产品的行为.
WP_Error
我很尴尬地承认,我花了比应该多几年的时间才开始正确使用 WP_Error
family of functions in my code. 我倾向于用自己的方式编写代码, 要么假设永远不会有值得编程关注的错误,要么逐案处理它们. 使用远程api就像一束激光一样可以打破这种心态, 因为它提供了一个非常方便和强大的用例 WP_Error
.
回想一下,我在前面提到过,我经常有一个PHP类,其目的是向远程API发出HTTP请求. 当你剥开所有的样板, all the data manipulation, all the secondary concerns, 这门课归根结底就是打电话 wp_remote_request()
以便从API获取HTTP响应对象. Conveniently, wp_remote_request()
will instead return a WP_Error
如果调用由于某种原因未能执行, but what about if the call succeeds in returning an HTTP response of an unfavorable type?
举个例子,也许我们给 /lists.json
端点,但此特定帐户尚未设置任何列表. 这将返回一个有效的HTTP响应,但状态码为400. 虽然这本身并不是致命的错误, 从一些前端代码的角度来看,它们想把这个API调用变成一个下拉菜单, a 400 might as well be a WSOD! Therefore, I find it helpful to do some additional parsing on the result of wp_remote_request()
, potentially returning a WP_Error
after all:
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()
在继续输出之前.
As a client, 您应该偶尔扮演恶意用户的角色, a confused user, and an impatient user. 以不应该使用的方式使用应用程序. 做一些开发者不希望你做的事情. Take note of what happens. 您会得到有用的错误消息吗? 您得到任何错误消息吗? If not, it may be worth sponsoring a body of work around better error handling.
ob_get_clean()
The modern programmable web, 几乎每个站点都使用其他站点的api, 并通过自己的API使用, 已经成为一个令人难以置信的强大的代码竞技场. 但正是这种品质也会让它变得相当缓慢.
It’s common for remote HTTP requests to be the most time-consuming parts of a given page load. For this reason, many API-driven components execute either via Ajax or cron. For example, 用于搜索电子邮件订阅者列表的自动建议可能应该根据需要ping远程数据源, upon each keystroke, rather than loading all 100,当页面加载时,在DOM内调用000个订阅者. If that’s not an option, 也许大型查询可以在夜间cron任务上同步, so that results can be pulled from a local mirror rather than the remote API.
这种方法的问题是很难调试. Instead of simply turning on WP_DEBUG
并让错误消息滚动到浏览器窗口, 您被困在浏览器网络控制台中, 或者将日志文件作为cron任务跟踪(希望如此)?) is executing. I find this uncomfortable.
One way to improve this situation is to make careful and strategic calls to error_log()
. But then again, 对于大型或繁忙的应用程序,日志记录的一个常见问题是, error logs can grow too large, or grow too quickly, 用于监视或解析. 因此,我们必须对记录的内容有选择性, putting just as much thought into that, as we do with our actual application logic. 遗憾的是,花了时间记录了一些奇怪的边缘情况错误,这些错误似乎只在一些不常见的cron任务上间歇性地发生,但却意识到,由于未能记录某些特定的数组成员,错误的真实性质再次逃避了您, say, of the offending value.
因此,我的哲学变成了, 我并不总是记录,但当我记录时,我会记录所有的事情. In other words, 在确定了一个特别令人担忧的功能之后, 我会把网撒得越宽越好
This amounts to var_dump()
将整个错误值放入错误日志文件中的单个条目中.
作为客户机,应该定期检查应用程序的总文件内存使用情况. If you notice that you’re suddenly butting up against the storage limits in your hosting account, 很有可能是错误日志失控造成的. 您的开发人员将从专注于更好的日志记录的工作周期中受益,您的客户也将受益!
请原谅本文的列表结构. 我无法将这些要点整合成一个更统一的文章主题,因为这些模式非常通用: 它们适用于任何JSON REST端点和任何WordPress输出.
这些都是我一遍又一遍地看到的模式, 不管远程API是什么, 或者我们在WordPress中使用它. 到目前为止,我已经将所有这些原则收集到一个插件样板中,这大大加快了我的工作速度. 你是否对每个项目都保留了相似的观点? 请分享它们,这样我就可以窃取它们并将它们添加到我的样板中!
一种使用WordPress发布API的便捷方式. 这个API可以被其他WordPress站点使用, other non-WordPress sites, 甚至是出版网站本身. 这是将WordPress用作“无头”CMS或仅用于小规模Ajax侦听器的流行方法.
API密钥是管理身份验证的常用方法. WordPress API兼容多种身份验证方法. 其中之一是WordPress REST API OAuth插件, 它为用户提供了管理API密钥的界面.
WP-JSON可以被认为是WordPress的RSS视图和它的普通前端视图的兄弟. 这是输出WordPress数据的另一种方式, although most human readers would not want to consume WordPress in this format. 相反,它的目的是供API客户端使用.
Portland, ME, United States
Member since February 20, 2017
Scott写过数百个WordPress主题和插件. He specializes in third-party API integration and he’s an active tech writer.
世界级的文章,每周发一次.
世界级的文章,每周发一次.
Join the Toptal® community.