首页 > 后端开发 > php教程 > 灵活的API设计:为您的PHP API管道创建钩子

灵活的API设计:为您的PHP API管道创建钩子

Joseph Gordon-Levitt
发布: 2025-02-08 10:57:09
原创
340 人浏览过

灵活的API设计:为您的PHP API管道创建钩子

设计应用程序编程接口(API)可能是一项具有挑战性的努力。良好的API具有简单易用的简单接口。在这个简单的接口背后可以是许多复杂的系统交互,这些交互实际上可能会使原本明确定义的端点任务的水域变得混乱。随着时间的流逝,可能会要求开发人员为现有终点“了解”其他业务逻辑。然后,在您不知不觉中,作为主要流程的一部分,一个API调用正在与十几个系统进行交互。

>如果我们可以开发一个简单的管道,但是可以在以后添加其他任务而不掩盖主流量的情况下添加其他任务,那不是很好吗?本文将向您展示如何从WordPress和编程中调整一个想法,以使您的API能够进行更强大的互动。

>

钥匙要点

  • >利用PHP API中的挂钩来增强灵活性并通过允许在不更改核心端点代码的情况下动态添加其他功能来保持干净的主流量。> 通过定义添加,删除和触发这些钩子的全局函数来实现挂钩,这些钩可在API的不同部分中使用,从而确保对主要应用程序逻辑的最小破坏。
  • >考虑将钩子放在API生命周期内的战略点上,例如成功的数据库插入或请求验证期间,根据API的状态或操作有条件地执行其他任务。
  • > 通过保持与挂钩相关的回调精益,以避免性能瓶颈,隔离回调功能以简化调试,并注意维持API响应的主动回调数量。
  • >保持与开发人员社区的互动,以接收反馈和要求新挂钩的请求,这可能会导致API的功能和灵活性不断提高,从而轻松地适应新的业务需求而无需进行大量重写。
  • >
  • 什么是挂钩/动作?
  • >钩子(又称操作/过滤器)是WordPress社区给事件及其相关回调的名称。如果您在编程方面有任何经验,那么您可能熟悉回调和发布者 - subscriber模式。在处理过程中,系统可能会触发一个事件,该事件将零归为零,以订阅该事件的许多功能。例如,在响应加载页面时,WordPress呼吁加载标题,加载标题,列出帖子或查找正确模板的功能。这些任务是在不混乱生成页面的主要过程的情况下运行的。
  • >

    钩背后的想法并不是什么新鲜事物,也不是WordPress发明的。但是,WordPress在其服务器端处理生命周期期间实现了它们,做得很好。在我看来,这种钩子的使用可能是平台拥有的最大功能。使用这些挂钩,用户可以编写自己的功能(无论是插件还是主题),可以将其连接到WordPress中,并在需要时运行您想要的任何代码。您需要更改发送给用户的标头吗?没问题:进入WP_headers事件,您可以在发现合适的情况下更改标题。

    为什么在API中使用钩?

    >钩子对许多事情都有好处,包括触发某些侧面任务,通过PHP curl命令召集另一个系统,构建对象并将其放入任务队列中,以后再由另一个系统捡起,发送电子邮件,发送电子邮件,发送电子邮件还有更多。这一切都可以完成,而无需蒙蔽给定端点的主要流(并且可能在此过程中强迫新的API版本)。

    如果端点是用于创建用户的终点,我们可以专注于在数据库中创建该用户记录,并在此过程中召集在此过程中正在侦听的任何人。也许在创建用户记录之后,我们发出了一个事件,上面写着“任何人都在听此操作,我只是创建了一个用户,这是他们的信息”。也许某些回调功能已经订阅了该事件,并且正在听,或者也没有。该活动并不真正在乎。

    >使用此系统,我们可以将API呼唤到可能在以后的某个时间编写的代码。我们可以做到这一点,而无需触摸API端点代码本身。为了证明这可能是如何工作的,让我们更改齿轮,并展示如何以PHP API开始实现这一目标的基本机制。请记住,当我们在此处使用PHP时,我们实际上可以使用其他语言在Web应用程序中实现类似的逻辑。

    构建基本机制

    为了开始,我们需要能够添加一个钩子/操作(从现在开始我将其称为“钩子”)。我们还需要能够卸下钩子并触发钩子的能力。定义这些机制后,我们只需要确保它们包含在API中,然后在API中找到可能需要调用这些钩子的位置即可。以下是我们可能想设置此的一种方式。

    这是hooks.php:

    >现在我们已经创建了hooks.php文件,我们只需要将其包含在我们的API中,以便可以看到这些功能。完成此操作后,这只是使用DO_HOOK将钩子插入我们的API的问题。

<span>// Global array which will hold all of our hooks
</span><span>// We will reference this array in each function to add/remove/call our hooks
</span><span>// The code below should also be seen by any callbacks we write for the system later.
</span><span>$hooks = [];
</span>
<span>// Below are global functions that can be seen from our API code
</span><span>// The add_hook method will allow us to attach a function (callback) to a given event name 
</span><span>function add_hook($event_name, $callback) {
</span>    <span>global $hooks;
</span>
    <span>if ($callback !== null) {
</span>        <span>if ($callback) {
</span>          <span>// We can set up multiple callbacks under a single event name
</span>            <span>$hooks[$event_name][] = $callback;
</span>        <span>}
</span>    <span>}
</span><span>}
</span>
<span>// Super easy to implement, we remove the given hook by its name
</span><span>function remove_hook($event_name) {
</span>    <span>global $hooks;
</span>
    <span>unset($hooks[$event_name]);
</span><span>}
</span>
<span>// When we want to trigger our callbacks, we can call this function 
</span><span>// with its name and any parameters we want to pass.
</span><span>function do_hook($event_name, ...$params) {
</span>    <span>global $hooks;
</span>
    <span>if (isset($hooks[$event_name])) {
</span>      <span>// Loop through all the callbacks on this event name and call them (if defined that is)
</span>      <span>// As we call each callback, we given it our parameters.
</span>        <span>foreach ($hooks[$event_name] as $function) {
</span>            <span>if (function_exists($function)) {
</span>                <span>call_user_func($function, ...$params);
</span>            <span>}
</span>        <span>}
</span>    <span>}
</span><span>}
</span>
登录后复制
登录后复制
登录后复制
作为一个简单的例子,假设我们有一个用于使用系统注册新用户的API。我们可能有一个REST API端点,称为 /adduser。以简单性的名义,我们还假设这里的目标是将新用户的名称和年龄插入我们的数据库用户表中。很简单,对吗?

>

<span>// Global array which will hold all of our hooks
</span><span>// We will reference this array in each function to add/remove/call our hooks
</span><span>// The code below should also be seen by any callbacks we write for the system later.
</span><span>$hooks = [];
</span>
<span>// Below are global functions that can be seen from our API code
</span><span>// The add_hook method will allow us to attach a function (callback) to a given event name 
</span><span>function add_hook($event_name, $callback) {
</span>    <span>global $hooks;
</span>
    <span>if ($callback !== null) {
</span>        <span>if ($callback) {
</span>          <span>// We can set up multiple callbacks under a single event name
</span>            <span>$hooks[$event_name][] = $callback;
</span>        <span>}
</span>    <span>}
</span><span>}
</span>
<span>// Super easy to implement, we remove the given hook by its name
</span><span>function remove_hook($event_name) {
</span>    <span>global $hooks;
</span>
    <span>unset($hooks[$event_name]);
</span><span>}
</span>
<span>// When we want to trigger our callbacks, we can call this function 
</span><span>// with its name and any parameters we want to pass.
</span><span>function do_hook($event_name, ...$params) {
</span>    <span>global $hooks;
</span>
    <span>if (isset($hooks[$event_name])) {
</span>      <span>// Loop through all the callbacks on this event name and call them (if defined that is)
</span>      <span>// As we call each callback, we given it our parameters.
</span>        <span>foreach ($hooks[$event_name] as $function) {
</span>            <span>if (function_exists($function)) {
</span>                <span>call_user_func($function, ...$params);
</span>            <span>}
</span>        <span>}
</span>    <span>}
</span><span>}
</span>
登录后复制
登录后复制
登录后复制

上面的代码是我们如何添加新用户的过度简单和普遍的视图。这个想法是,如果某人打电话给我们的API /Adduser端点,他们最终将在此功能中得出此功能,从而将用户的名称和年龄从已发布的数据中提取出来。我们首先检查以确保他们发布(作为适当的休息规则规定),然后尝试将用户插入用户表中。

接下来,如果成功插入了用户,我们想调用钩子,以使任何创建用户的代码侦听(这类似于用其他语言提出事件)。

当需求变化时该怎么办

几个月后,我们让我们的营销部门坚持认为,当创建新用户时,应将电子邮件发送给用户的详细信息。我们可能倾向于将助手功能写入API,然后从此端点代码中调用它。太好了……如果这就是要求的。但是,如果支持团队后来来到您身边,并希望您还将用户添加到他们的Zendesk系统中。因此,您还编写另一个功能,并将其拨打到此端点。

接下来,您知道,此端点不仅是将用户添加到我们的网站数据库中,而且还呼吁发送电子邮件,将用户添加到Zendesk,Jira和Microsoft Cloud,然后处理其成功/失败结果。所有这些其他东西确实从将用户添加到我们的数据库的清晰点中。我们想调用一个事件,并让其他代码在创建用户并做自己的事情时聆听 - 而无需我们修改此端点。也许没有其他服务在乎添加新用户,因此没有人被要求做任何事情。终点不必关心。很棒,对

>让我们以钩子的名字来继续我们的榜样。这是所有回调代码都需要使用的名称。同样,其他语言将此设置称为“事件”,因此请务必用给定的语言查找它以了解更多信息。

我们将调用hook add_user。简单而直截了当,你不觉得吗?一旦有名,我们就可以决定要在哪里称呼此钩子。我认为成功插入后是个好主意:

<span>// POST endpoint for adding a user (part of a larger API class)
</span><span>public function addUser($name, $age) {
</span>  <span>if ($this->request->method === 'post') {
</span>    <span>try {
</span>      <span>$this->db->insert('users', ['name' => $name, 'age' => $age]);
</span>      <span>return new Response(200, 'User created successfully!');
</span>    <span>} catch (Exception $e) {
</span>      <span>// Oops, something went wrong.
</span>      <span>// Do some logging or whatever.
</span>    <span>}
</span>  <span>}
</span>
  <span>// If not a POST request, return http status 400
</span>  <span>return new Response(400, 'Bad request');
</span><span>}
</span>
登录后复制

>现在,我们可以有数十个回调函数收听添加_user钩或根本没有。也许我们有一个回调,负责将用户插入Zendesk,而另一个将插入姓名和年龄并为营销生成电子邮件。只要可以在API项目中看到hooks.php代码,就可以在代码库中的其他地方生活。我通常将回调函数放在单独的文件中,并将该文件也包括在API中。以下是回调的一个示例,现在可以利用我们创建的这个新钩子:

<span>// Global array which will hold all of our hooks
</span><span>// We will reference this array in each function to add/remove/call our hooks
</span><span>// The code below should also be seen by any callbacks we write for the system later.
</span><span>$hooks = [];
</span>
<span>// Below are global functions that can be seen from our API code
</span><span>// The add_hook method will allow us to attach a function (callback) to a given event name 
</span><span>function add_hook($event_name, $callback) {
</span>    <span>global $hooks;
</span>
    <span>if ($callback !== null) {
</span>        <span>if ($callback) {
</span>          <span>// We can set up multiple callbacks under a single event name
</span>            <span>$hooks[$event_name][] = $callback;
</span>        <span>}
</span>    <span>}
</span><span>}
</span>
<span>// Super easy to implement, we remove the given hook by its name
</span><span>function remove_hook($event_name) {
</span>    <span>global $hooks;
</span>
    <span>unset($hooks[$event_name]);
</span><span>}
</span>
<span>// When we want to trigger our callbacks, we can call this function 
</span><span>// with its name and any parameters we want to pass.
</span><span>function do_hook($event_name, ...$params) {
</span>    <span>global $hooks;
</span>
    <span>if (isset($hooks[$event_name])) {
</span>      <span>// Loop through all the callbacks on this event name and call them (if defined that is)
</span>      <span>// As we call each callback, we given it our parameters.
</span>        <span>foreach ($hooks[$event_name] as $function) {
</span>            <span>if (function_exists($function)) {
</span>                <span>call_user_func($function, ...$params);
</span>            <span>}
</span>        <span>}
</span>    <span>}
</span><span>}
</span>
登录后复制
登录后复制
登录后复制

我们可以在哪里放置这些钩子?

在上面的代码中,我们在单个端点中使用钩子演示。仅在调用 /adduser端点时才触发此钩子,并且只有在插入成功后才触发。但这不是您唯一可以使用这些钩子的地方。也许您在API类中有一些路由代码,可以通过检查API密钥是否有效,或者您甚至收到某种类型的请求。

>您可以在API中的全球级别上放置一个钩子,以便每个请求触发它。然后,在以后的某个时间,有人可以编写一个记录器,将其附加到您创建的API_Init挂钩上,然后突然开始记录对API的所有请求,同样,不是触摸主API类代码。同样的钩子还可能附加一个回调,如果它开始看到有人用请求猛击您的API,则可以检查API滥用并将其报告给您的信息技术部门。

下面的图像是所有这些图表的图表。

灵活的API设计:为您的PHP API管道创建钩子>由于您可以在多个位置使用此机制,因此您甚至可以在API端点的开头,中间和结尾处使用钩子。您还可以在处理请求的整个API生命周期的各个点上有钩子。这实际上取决于您在插入这些do_hook呼叫的位置上的设计。

>

最佳实践

>现在让我们介绍一些最佳实践,以供您和您的开发人员遵循。

>提示1:保持钩子瘦弱和平均

>

>要记住的一件事是,这些挂钩仍然会呼唤将在单个线程中执行的代码。除非您在回调中触发某些内容将任务踢到某些背景过程或其他服务,否则API仍将运行此额外的代码(触发钩子时)。这意味着我们应该尽最大努力保持任何回调代码精益和卑鄙。长期运行的回调代码将减慢端点或整个API。

>提示2:使每个回调隔离且易于调试

>但是,通过设计该结构的方式,为您的钩子添加和删除回调功能很容易做,并且调试同样容易。查找哪个回调是罪犯(也许每个回调记录一些数据),并找出卡住的位置。然后,在错误修复或通过回调代码工作之前,根本没有订阅钩子,又不触摸端点/API代码中的任何内容,而不会阻止您的API代码在生产中运行。

提示3:考虑性能,不要滥用钩子

>请注意您在钩子上附加多少个回调也很重要。少数几个快速回调是可以的,但是单个挂钩上的100个回调,每秒钟执行一秒钟确实可以阻止您的API。我们需要快速的API调用,并且每个回调都可以轻松拖动响应时间。同样,如果您发现回调速度慢,请将任务扔到背景过程或队列系统中,以后将由另一个服务捡起。我经常在Laravel之类的系统中使用工作来处理此类任务。也许将用户任务添加到Laravel作业队列中,然后继续进行API处理。

>

提示4:与您的开发社区保持联系 最后,确保您与可能使用这些挂钩的开发人员保持联系。通常,开发人员使用您的钩子和编写回调,与创建API中创建钩子的人并不是一开始。随着API的成熟,您可能会开始看到在不同地方添加更多钩子和更精细的粒度的请求。他们可能会要求在插入用户之前和之后插入用户之前/之后的挂钩之前/之后。他们还可能要求将其他信息传递给他们的回调(不仅是他们的名称和年龄,还包括插入用户的新ID)。以这些要求为一个好兆头,表明您的开发人员发现该机制有用,并看到扩大API在相关系统中的影响的潜力。拥有一个非常容易“挂接”并执行一小块代码以产生巨大影响的系统真的感觉很好。

>

使用这种方法,天空是您可以拥有的API所做的限制。在与其他系统打交道时,这一切都可以实现,同时保持端点的主要流量清晰,没有噪音。

结论

在本文中,我们讨论了什么是钩子/动作以及如何使用它们。我们提供了一些示例PHP代码,您可以在PHP API中使用这些代码来实现“钩”,以及如何使用回调将其绑在该钩子中。我们还讨论了在一般API级别(全球范围内更多)以及端点上添加钩子。除此之外,我们还讨论了该系统的一些缺点,并且可以使您的回调变得精明和卑鄙,这是一个好主意。但是,如果您确实有一个长期运行的回调,我们提到了一些处理此类流程以防止它们影响您的API管道的策略。

如果您实现了此系统,则您也可以获得WordPress社区(以及总体程序员)多年来所享受的一些最大功能。您还可以节省很多时间和头痛,从必须直接修改API代码,并且可以专注于小回调代码。您还可以添加和删除可能与其他系统的整个集成在一起的回调。所有这些功能 - 不必重新发布您的API管道代码!这是一个很好的交易,对吧?有了这个系统,我一天都设法进行了一些简单的集成,现在您也可以做到。

>

感谢您的阅读!

关于灵活的API设计和PHP挂钩的常见问题(常见问题解答)

> PHP API管道中挂钩在PHP API管道中的重要性是什么?它们允许开发人员在程序执行中的特定点插入自定义代码,而无需更改核心代码。这使得在不破坏整个系统的情况下更容易添加,修改或删除功能。钩子本质上是由特定动作触发的事件,可以用来以干净且有条理的方式扩展应用程序。

>

>如何为我的PHP API管道创建挂钩?对于您的PHP API管道,涉及定义可以执行自定义代码的代码中的特定点。这通常是使用事件和听众完成的。当发生特定事件时,触发相应的侦听器,执行自定义代码。这使您可以在运行时修改应用程序的行为,提供高度的灵活性和适应性。

>

>设计灵活的API的最佳实践是什么?几种最佳实践。首先,保持API简单而直观非常重要,从而使开发人员易于理解和使用。其次,应将API设计为可扩展的,从而允许添加新功能而不会破坏现有功能。第三,提供清晰,全面的文档至关重要,帮助开发人员了解如何有效使用API​​。最后,使用标准的HTTP方法和状态代码可以使API更容易预测,更易于使用。

>

PHP与API设计的其他语言相比如何?

PHP是API的流行选择设计由于其简单性和灵活性。它支持包括JSON和XML在内的广泛的数据格式,使创建可以被各种客户消费的API易于使用。 PHP还拥有一个庞大而活跃的社区,为开发人员提供了丰富的资源和支持。但是,像任何语言一样,它具有其优点和劣势,并且语言的选择应基于项目的特定要求。

> API设计中有哪些共同的挑战,如何解决?

API设计可以提出一些挑战,包括确保一致性,管理版本控制和有效处理错误。一致性可以通过遵循既定的惯例和标准来维持。可以通过在API URL或请求标头中包含版本编号来管理版本控制。应该优雅地处理错误,提供清晰且有用的错误消息,以帮助开发人员诊断和解决问题。

>

>我如何确保API的安全性?措施。这包括使用安全通信协议,例如HTTP,实施身份验证和授权机制,以及验证和消毒输入数据以防止注射攻击。定期的安全审核和更新还可以帮助识别和修复潜在的漏洞。

>

>如何测试我的API以确保其正常工作正确吗?

>测试您的API涉及向API端点和API的请求验证响应。这可以使用邮递员等工具手动完成,也可以自动使用测试框架来完成。测试API的各个方面,包括功能,性能和安全性很重要。

>如何处理API中的错误?

>处理API中的处理错误涉及返回适当的HTTP状态代码和错误消息。这有助于开发人员了解出了什么问题以及如何解决问题。记录错误和分析的错误也很重要。

>我如何提高API的性能?

提高API的性能可能涉及多种策略,包括优化数据库查询,实施,实施缓存,并使用有效的数据结构和算法。定期的性能测试和监控可以帮助识别瓶颈和改进区域。

>如何使我的API保持最新状态?根据开发人员的反馈和业务需求的变化来更新API设计。及时向API用户传达任何更改,并在必要时为API的旧版本提供支持。

以上是灵活的API设计:为您的PHP API管道创建钩子的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板