增强 WordPress:打造改进的 API 和库
感觉我们接触到的一切都是经过精心设计的:网站、电话、地铁地图等等。即使是我们过去认为理所当然的东西:恒温器、烟雾探测器和汽车仪表板现在也得到了仔细的用户体验处理。
设计不仅仅是外观和感觉:它还需要考虑用户与我们的设备/工具/屏幕/对象交互所需的各种方式。
这也适用于编程。
(未)设计的编程
编程语言是一个庞大而复杂的世界。即使是许多编程势利小人认为太“简单”的 PHP,实际上也是函数和类的相当复杂的组合,其行为方式非常不一致。
多年来,语法、方法和命名在数百万不同的用户和应用程序中不断发展。大多数倾向于反映内部的底层构造 - 不一定是您想要如何使用它。
API 设计的伟大时刻:jQuery
>当我在 2006 年左右开始编写 JavaScript 时,情况一团糟。以下是我如何找到具有特定类的标签并将其在 DOM 中移动的方法:
var uls = getElementsByTagName("ul"); var classToSearch = "foods"; for (var i = 0; i < uls.length; i++) { var classes = uls[i].getClasses(); for (var j = 0; j < classes.length; j++){ if (classes[j] == classToSearch){ myUL = uls[i]; } } } var $li = document.createElement('li'); $li.innerHTML = 'Steak'; myUL.innerHTML += $li;
完成!
jQuery 让 JavaScript 再次变得有趣。在 2000 年代末,这种影响是如此巨大,以至于我记得我父亲问我他在《华尔街日报》上读到的“一些奇怪的事情”。但尽管效果巨大,jQuery 并没有为 JavaScript 添加任何“新功能”。它只是将开发人员必须做的事情分解为非常清晰的模式。
他们没有重新发明如何在页面上查找内容,而是利用了人们已经知道的东西:CSS 选择器。然后,只需收集大量常见操作并将它们组织成几十个函数即可。让我们再次尝试前面的示例,现在使用 jQuery:
var $li = $('<li>Steak</li>'); $("ul.foods").append($li);
2006 年,我买了一本 680 页的 Ajax 书籍。有了 jQuery 出色的 API,它几乎被这个取代了:
$.post();
WordPress API
虽然 API 已经开始代表“第三方服务”,但它仅仅意味着与系统对话的编程接口。就像 Twitter API 或 Facebook API 一样,WordPress API 也存在。您不会进行原始数据库查询来创建帖子,对吧?您使用 wp_insert_post。
但是许多设计漏洞困扰着 WordPress API。您可能使用 get_the_title 但 get_the_permalink 会生成错误,您使用 get_permalink 。嘿,当您有一个长达数十年的开源项目,涉及数千人的代码和数百万用户时:您会遇到一些怪癖。
通过掩盖这些怪癖并根据您正在编写的程序员(可能是您)的习惯和行为进行编写,您可以节省大量时间。您可以在这里设计正确的界面来对您日常使用的插件和主题进行编程。
解决方案
为了加快工作速度并减少重复性任务,我创建了库来处理我一直需要的命令和自定义设置。
1。常见任务的快捷方式
以获取帖子缩略图的来源为例。事实证明,WordPress 没有内置功能来根据帖子 ID(仅附件 ID)获取缩略图。
这意味着我经常发现自己这样做:
$thumb_id = get_post_thumbnail_id( get_the_ID() ); $src = wp_get_attachment_thumb_url( $thumb_id ); echo '<img alt="" src="' . $src . '" />';
但是一定有更好的方法!
function get_thumbnail_src( $post ){ $thumb_id = get_post_thumbnail_id( $post ); $src = wp_get_attachment_thumb_url( $thumb_id ); return $src; } echo '<img alt="" src="' . get_thumbnail_src( get_the_ID() ) . '" />';
2:不可预测的输入,可预测的输出
好多了!事实上,您发现自己一直在使用它,然后与公司的其他开发人员共享。
你的朋友遇到了麻烦,所以他打电话给你来调试,你看到:
echo '<img src="' . get_thumbnail_src( get_post() ) . '" alt="增强 WordPress:打造改进的 API 和库" >';
看来他不小心使用了 get_post 而不是 get_the_ID。你对他大喊大叫。但是等一下,为什么不让它更容易被接受呢?
也许我们可以调整我们的函数,以便它可以采用 WP_Post 对象,并且仍然为用户提供他们所期望的内容。让我们回到该函数:
function get_thumbnail_src( $post ){ if ( is_object( $post ) && isset( $post->ID ) ){ $post = $post->ID; } else if ( is_array( $post ) && isset( $post['ID'] ) ) { $post = $post['ID']; } $thumb_id = get_post_thumbnail_id( $post ); $src = wp_get_attachment_thumb_url( $thumb_id ); return $src; }
因此,如果他们发送 WP_Post 对象或一个数组,您的函数仍然可以帮助他们获得所需的内容。这是成功 API 的重要组成部分:隐藏混乱的内部结构。您可以为 get_thumbnail_src_by_post_id 和 get_thumbnail_src_by_wp_post_object. 制作单独的函数
事实上,对于更复杂的转换可能更可取,但是您可以通过将单个函数路由到正确的子例程来简化界面。无论用户发送什么内容,该函数都会始终返回图像源的字符串。
让我们继续:如果他们什么也没发送怎么办?
3。合理的默认值
function get_thumbnail_src( $post = false ) { if ( false === $post ) { $post = get_the_ID(); } else if ( is_object( $post ) && isset( $post->ID ) ) { $post = $post->ID; } else if ( is_array( $post ) && isset( $post['ID'] ) ) { $post = $post['ID']; } $thumb_id = get_post_thumbnail_id( $post ); $src = wp_get_attachment_thumb_url( $thumb_id ); return $src; }
我们再次进行了简化,因此用户无需发送帖子,甚至无需发送帖子 ID。在循环中时,所需要做的就是:
echo '<img src="'.get_thumbnail_src().'" / alt="增强 WordPress:打造改进的 API 和库" >';
我们的函数将默认为当前帖子的 ID。这正在变成一个非常有价值的功能。为了确保它能很好地发挥作用,让我们将它包装在一个类中,这样它就不会污染全局命名空间。
/* Plugin Name: JaredTools Description: My toolbox for WordPress themes. Author: Jared Novack Version: 0.1 Author URI: http://upstatement.com/ */ class JaredsTools { public static function get_thumbnail_src( $post = false ) { if (false === $post ) { $post = get_the_ID(); } else if ( is_object( $post ) && isset( $post->ID ) ) { $post = $post->ID; } else if ( is_array( $post ) && isset( $post['ID'] ) ) { $post = $post['ID']; } $thumb_id = get_post_thumbnail_id( $post ); $src = wp_get_attachment_thumb_url( $thumb_id ); return $src; } }
并且请不要在您的类前面添加 WP。我将其设为公共静态函数,因为我希望它可以在任何地方访问,并且它不会改变:输入或执行不会更改函数或对象。
该函数的最终调用是:
echo '<img src="'.JaredsTools::get_thumbnail_src().'" alt="增强 WordPress:打造改进的 API 和库" >';
先设计,后构建
让我们继续处理更复杂的需求。当我编写插件时,我发现我总是需要生成不同类型的错误和/或更新消息。
但是基于事件的语法一直困扰着我:
add_action( 'admin_notices', 'show_my_notice'); functon show_my_notice(){ echo '<div class="updated"><p>Your thing has been updated</p></div>'; }
WordPress 遵循这种基于事件的架构有很多充分的理由。但这并不直观,除非您想坐下来记住不同的过滤器和操作。
让我们将此匹配作为最简单的用例:我需要显示管理员通知。我喜欢首先设计这个 API:我找出在代码中引用该函数的最佳方式。我希望它读起来像这样:
function thing_that_happens_in_my_plugin($post_id, $value){ $updated = update_post_meta($post_id, $value); if ($updated){ JaredsTools::show_admin_notice("Your thing has been updated") } else { JaredsTools::show_admin_notice("Error updating your thing", "error"); } }
一旦我设计了端点,我就可以满足设计要求:
class JaredsTools { public static function show_admin_notice($message, $class = 'updated'){ add_action('admin_notices', function() use ($message, $class){ echo '<div class="'.$class.'"><p>'.$message.'</p></div>'; }); } }
好多了!现在我不需要创建所有这些额外的函数或记住疯狂的钩子名称。在这里,我使用 PHP 匿名函数(也称为“闭包”),它让我们可以将函数直接绑定到操作或过滤器。
这可以让您避免在文件中出现大量额外的函数。 use 命令让我们将参数从父函数传递到子闭包中。
保持直觉
现在另一位同事打电话给您。她不知道为什么她的管理通知没有变成红色:
JaredsTools::show_admin_notice("Error updating your thing", "red");
这是因为她正在发送“红色”(她希望将盒子变成红色),而实际上她应该发送触发红色的类名称。但为什么不让它变得更容易呢?
public static function show_notice( $message, $class = 'updated' ) { $class = trim( strtolower( $class ) ); if ( 'yellow' == $class ) { $class = 'updated'; } if ('red' == $class ) { $class = 'error'; } add_action( 'admin_notices', function() use ( $text, $class ) { echo '<div class="'.$class.'"><p>' . $text . '</p></div>'; }); }
我们现在已经接受了更多的用户容忍度,这将使我们在几个月后回来使用它时更容易分享。
结论
在构建了其中一些之后,以下是我学到的一些原则,这些原则使这些原则对我和我的团队真正有用。
1.首先进行设计,让函数的构建符合人们想要使用它的方式。
2. 拯救你的键盘!为常见任务创建快捷方式。
3. 提供合理的默认值。
4. 保持最小化。让您的库来处理处理。
5. 对输入要宽容,对输出要精确。
6. 也就是说,使用尽可能少的函数参数,最多四个是一个很好的参数。之后,您应该将其设为选项数组。
7. 将您的库组织成单独的类,以涵盖不同的领域(管理、图像、自定义帖子等)。
8. 包含示例代码的文档。
在 Upstatement,我们的 Timber 库使构建主题变得更加容易,而 Jigsaw 提供了节省时间的快捷方式来自定义每个安装。
这些工具节省的时间让我们可以花更多时间构建每个网站或应用程序的新的和创新的部分。通过执行深奥的命令(例如向管理帖子表添加一列)并制作简单的界面:我们公司的任何设计师或开发人员都可以使用与专业 WordPress 开发人员相同的能力完全自定义每个网站。
增强 WordPress:打造改进的 API 和库的详细内容,更多请关注红帽云邮其它相关文章!