如何制作出色的 WP 插件二(架构篇)

PHP 程序从来不缺好的架构,WP 从来都没有好的架构,无论是从安全性上或效率上,WP 都称不上优秀。但这并不能成为制作出九流插件的理由,人不能自暴自弃。

在上篇文章《如何制作出色的 WP 插件一(注释篇)》已讲述了插件的注释格式,接下来继续讲述插件应有怎样的基础架构,才能成为一款优秀的插件。

读前须知

本章节涉及到 PHP7 相关知识,以及基本的面向对象概念,您可以在读前去了解一下这些知识,否则理解的难度可能有所提高。

文件命名

在编写之前,先将插件文件名命名为为:MyPlugin.php,并放在 MyPlugin 的插件目录里面。如不知道如何命名,请查阅上一篇《如何制作出色的 WP 插件一(注释篇)》。

严格模式

从 PHP 7.1 开始,PHP 支持严格模式,意味一旦开启了这个模式,插件的所有变量、参数和返回值都需要符合预期的类型,例如 md5 函数,其参数必须为字符串,md5(123) 这种写法是错误的,因为 123 是数字而不是字符串。需改为 md5('123') 才是正确的。

至于为什么要启用严格模式,因为一是可以让编辑器更好无需推导就能提示类型,二是不容易发生类型转换的漏洞,三是可为未来的 PHP (PHP8 JIT)标准做好铺垫,减少维护成本。

所以,在写插件的时候,您应在上篇文章《注释篇》中的注释下面,加入如下代码:

declare(strict_types = 1);

命名空间

WP 的插件是原生 PHP 代码构成,故此里面的函数或变量都是全局注册的,如果有两个插件都有一样名称的函数名,这将会导致发生致命错误,PHP 无法继续工作。为了解决这个问题,一律应在插件里使用命名空间,例如紧接上述代码,在此加入下列命名空间代码:

namespace InnStudio\Plugin\MyPlugin;

禁止非法访问

因为 WP 插件是 PHP 文件,而且插件路径可以从 URL 直接访问,如没有做防御处理,将会导致一些异常错误发生,暴露服务器的信息。因此您应该增加这类的判断,防止非法访问,紧接上述代码,再次加入如下代码:

\defined('\\AUTH_KEY') || \http_response_code(500) && die;

上述代码意思为:检测 AUTH_KEY 这个全局 WP 常量,如果没有则输出 500 错误并终止脚本执行。AUTH_KEY 全局常量是在 wp-config.php 配置文件中定义的,因为直接访问插件文件,AUTH_KEY 全局常量是无效的,故能阻止非法访问。

一般情况下,如果插件复杂度不高,功能数量不超过 5 个,可以使用一个类来实现。例如我们要制作一款功能仅能在前台页面(WP 默认主题)弹出警告框的插件,类代码基本结构可为下(继续在上述代码添加):

// 定义插件执行类
final class MyPlugin
{
    // 定义构造函数
    public function __construct()
        {
            // 定义一个在 'wp_head' 钩子的匿名函数
            \add_action('wp_head', function():void{
                // 输出警告框
                echo '<script>alert();</script>';
            });
        }
}

在上述代码中,我们构建了一个功能非常简单的类,仅能在前台页面中弹出一个空内容的警告框,其中 wp_head 即在前台页面的 <head> 区域输出 JS 警告框代码。但在这段代码中,只是定义了一个类,并没有对其实例化(调用)。

调用

定义了上述类后,我们需要对其进行实例化,可继续编写(在上述代码继续添加):

new MyPlugin();

在上述代码中,我们已经对类进行了实例化,当加载插件的时候,就会生效了。

完成

到目前位置,这个插件的所有代码应该类似如下:

<?php

// Plugin Name: 我的插件
// Plugin URI: https://inn-studio.com
// Description: 这是我的插件描述
// Author: 小明
// Author URI: https://inn-studio.com/how-to-code-good
// Version: 1.0.0
// PHP Required: 7.3

declare(strict_types = 1);

namespace InnStudio\Plugin\MyPlugin;

\defined('\\AUTH_KEY') || \http_response_code(500) && die;

// 定义插件执行类
final class MyPlugin
{
    // 定义构造函数
    public function __construct()
    {
        // 定义一个在 'wp_head' 钩子的匿名函数
        \add_action('wp_head', function (): void {
            // 输出警告框
            echo '<script>alert();</script>';
        });
    }
}

new MyPlugin();

至此,本插件所在位置应该为 wp-content/plugins/MyPlugin/MyPlugin.php,这时候我们可以在后台看见此插件存在于列表中。

插件列表
插件列表

点击启用,查看网站首页,即可看到弹出警告框。

空白警告框
空白警告框

进阶

在上述代码中,我们在函数前面用到了一个反斜杠\,这是什么意思呢?这是因为我们用到 PHP 的命名空间,所有全局的用户(WP)函数,都需要加上全局符号\来表示这个函数是全局的。

其中如果函数是 PHP 内置函数,也最好加上,因为这可以加快函数的解析,而不是先从本命名空间中查找,然后在查找 PHP 内存函数。

结语

在学习了本系列后,您应该可以能写出一个弹出警告框的插件了,虽然没什么作用,但任何事情都会有第一步的。

接下来,将会有更多的篇章等着我们,共同期待吧!

热门评论
© INN STUDIO