WordPress 插件开发最小可用示例(含后台设置页)

· wordpress · 阅读 2
摘要

先说结论:一个合格的 WordPress 插件最少需要三样东西——头部声明、一个钩子挂载点、一个可选的设置页。下面从零写一个「文章末尾自动加版权声明」的插件,全部代码不到 100 行,可以直接改成你自己要的功能。 一、目录与文件结构 wp-

先说结论:一个合格的 WordPress 插件最少需要三样东西——头部声明、一个钩子挂载点、一个可选的设置页。下面从零写一个「文章末尾自动加版权声明」的插件,全部代码不到 100 行,可以直接改成你自己要的功能。

一、目录与文件结构

wp-content/plugins/my-copyright/
├── my-copyright.php   (主文件,必须)
└── readme.txt         (可选,但建议有)

常见错误:文件夹名和主文件名不一致、主文件放在子目录里,都会导致后台看不到插件。

二、主文件头部声明(少了它插件不出现)

<?php
/*
Plugin Name: My Copyright
Description: 在文章末尾追加版权声明。
Version: 1.0.0
Author: Your Name
License: GPL-2.0-or-later
Text Domain: my-copyright
*

if ( ! defined( 'ABSPATH' ) ) {
    exit; // 防止直接访问文件
}

Plugin Name 是后台显示的名字,必须有。ABSPATH 判断是安全基线的第一步,所有插件都该有。

三、挂第一个钩子:过滤器 the_content

add_filter( 'the_content', 'myc_append_copyright' );

function myc_append_copyright( $content ) {
    // 只在单篇文章页、主循环里生效
    if ( ! is_singular( 'post' ) || ! in_the_loop() || ! is_main_query() ) {
        return $content;
    }

    $text = get_option( 'myc_text', '本文为原创内容,转载请注明出处。' );
    $html = '<div class="myc-copyright">' . esc_html( $text ) . '</div>';

    return $content . $html;
}

三个判断条件缺一不可:

  • is_singular('post'):避免出现在列表页、页面、归档页。
  • in_the_loop():避免影响侧栏、相关文章等二次循环。
  • is_main_query():避免影响查询结果里的其他内容。

漏了这三个判断,最常见的现象是「版权声明出现在所有地方,包括后台摘要和 RSS」。

四、加一个后台设置页(3 个函数就够)

1. 在后台菜单注册页面

add_action( 'admin_menu', 'myc_add_menu' );

function myc_add_menu() {
    add_options_page(
        '版权声明设置',          // 页面标题
        'My Copyright',          // 菜单名
        'manage_options',        // 权限
        'my-copyright',          // slug
        'myc_render_page'        // 回调
    );
}

manage_options 是关键权限,只有管理员能看。权限写小了普通用户看不见,写大了有安全问题。

2. 渲染表单

function myc_render_page() {
    ?>
    <div class="wrap">
        <h1>版权声明设置</h1>
        <form method="post" action="options.php">
            <?php settings_fields( 'myc_group' ); ?>
            <?php do_settings_sections( 'myc_group' ); ?>
            <table class="form-table">
                <tr>
                    <th><label for="myc_text">声明文字</label></th>
                    <td>
                        <input type="text" id="myc_text" name="myc_text"
                               value="<?php echo esc_attr( get_option( 'myc_text' ) ); ?>"
                               class="regular-text">
                    </td>
                </tr>
            </table>
            <?php submit_button(); ?>
        </form>
    </div>
    <?php
}

注意 action="options.php" 是 WordPress 处理设置保存的入口,不要改成自己的地址。esc_attr() 输出时必须转义。

3. 注册设置项

add_action( 'admin_init', 'myc_register_settings' );

function myc_register_settings() {
    register_setting( 'myc_group', 'myc_text', [
        'type'              => 'string',
        'sanitize_callback' => 'sanitize_text_field',
        'default'           => '本文为原创内容,转载请注明出处。',
    ] );
}

sanitize_callback 是必填的,不写就可能被写入 HTML 或脚本。这是插件审核被打回最多的原因之一。

五、加上样式(只在本页加载)

add_action( 'wp_enqueue_scripts', 'myc_enqueue' );

function myc_enqueue() {
    wp_register_style( 'myc-style', false );
    wp_enqueue_style( 'myc-style' );
    wp_add_inline_style( 'myc-style', '.myc-copyright{border-top:1px solid #eee;padding-top:12px;margin-top:24px;font-size:14px;color:#666}' );
}

用 wp_add_inline_style 就不需要额外的 css 文件,适合极小的插件。

六、卸载时清理数据

在插件目录建 uninstall.php:

<?php
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) { exit; }
delete_option( 'myc_text' );

不写这个文件,用户删了插件,数据库里还留着 option,属于不干净的做法。

七、命名前缀这件事,别嫌啰嗦

PHP 里函数名是全局的,两个插件用同名函数会直接白屏。规范做法:

  • 所有函数加统一前缀(如 myc_)。
  • 或者用类包装,把函数收进 class 里。
  • option 名、slug、样式句柄也统一前缀。

真实事故:某站装了 A 插件和 B 插件,两者都有 get_meta(),一启用就 Fatal error。改名 5 分钟的事,排查要 2 小时。

八、自测清单

检查项状态
后台能看到插件并启用□
文章页出现声明,列表页没有□
设置页能保存并回显□
普通用户看不到设置页□
WP_DEBUG 开启下无 notice□
禁用后前台无残留□

把这个示例跑通,你就已经会了 WordPress 插件开发的核心三件事:钩子、设置、安全转义。剩下都是往这个骨架上加功能。