<?php
/*
Plugin Name: My First Plugin
Plugin URI: https://example.com/my-first-plugin
Description: This is my first WordPress plugin.
Version: 1.0
Author: Your Name
Author URI: https://example.com
License: GPL2
*/
4.3 插件的基本功能
添加一些基本功能,如在 WordPress 后台显示一个简单的信息:
function my_first_plugin_admin_notice() {
echo '<div class="notice notice-success is-dismissible">
<p>My First Plugin is activated!</p>
</div>';
}
add_action('admin_notices', 'my_first_plugin_admin_notice');
// 动作钩子
add_action('wp_footer', 'my_first_plugin_footer_message');
function my_first_plugin_footer_message() {
echo '<p>Thank you for visiting my website!</p>';
}
// 过滤器钩子
add_filter('the_content', 'my_first_plugin_content_filter');
function my_first_plugin_content_filter(content . '<p>Custom content added by My First Plugin.</p>';
}
class My_First_Plugin {
public function __construct() {
add_action('init', array(args = array(
'public' => true,
'label' => 'Custom Post',
);
register_post_type('custom_post', my_first_plugin = new My_First_Plugin();
17.2 使用命名空间
使用命名空间可以避免类名和函数名冲突:
namespace MyFirstPlugin;
class Main {
public function __construct() {
add_action('init', array(args = array(
'public' => true,
'label' => 'Custom Post',
);
register_post_type('custom_post', main = new Main();
class My_First_Plugin {
private static this, 'init'));
}
public static function get_instance() {
if (self::instance = new self();
}
return self::cache_key = 'my_first_plugin_cached_data';
cache_key);
if (data = '...';
wp_cache_set(data, '', 3600);
}
return wpdb;
wpdb->prefix . 'my_first_plugin_table';
wpdb->get_charset_collate();
table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
name tinytext NOT NULL,
email text NOT NULL,
date datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
PRIMARY KEY (id)
) sql);
}
register_activation_hook(__FILE__, 'my_first_plugin_create_table');
19.2 插入数据
function my_first_plugin_insert_data(email) {
global table_name = wpdb->insert(
name,
'email' => wpdb;
wpdb->prefix . 'my_first_plugin_table';
wpdb->get_results("SELECT * FROM results;
}
function my_first_plugin_do_custom_action() {
do_action('my_first_plugin_custom_action');
}
function my_first_plugin_add_custom_action() {
echo 'Custom Action Triggered!';
}
add_action('my_first_plugin_custom_action', 'my_first_plugin_add_custom_action');
21.2 创建自定义过滤器
function my_first_plugin_apply_custom_filter(content);
}
function my_first_plugin_modify_content(content . ' - Modified by custom filter';
}
add_filter('my_first_plugin_custom_filter', 'my_first_plugin_modify_content');
function my_first_plugin_form_handler() {
if (!isset(_POST['my_first_plugin_nonce'], 'my_first_plugin_form_nonce')) {
wp_die(__('Nonce verification failed', 'my-first-plugin'));
}
if (!current_user_can('manage_options')) {
wp_die(__('You do not have sufficient permissions to access this page.', 'my-first-plugin'));
}
_POST['name']);
// 处理表单数据,例如保存到数据库
wp_redirect(admin_url('options-general.php?page=my-first-plugin&message=success'));
exit;
}
add_action('admin_post_my_first_plugin_form_action', 'my_first_plugin_form_handler');
32. 使用 AJAX
32.1 注册 AJAX 动作
function my_first_plugin_ajax_handler() {
check_ajax_referer('my_first_plugin_nonce', 'security');
if (!current_user_can('manage_options')) {
wp_send_json_error(__('You do not have sufficient permissions to access this page.', 'my-first-plugin'));
}
response);
}
add_action('wp_ajax_my_first_plugin_action', 'my_first_plugin_ajax_handler');
32.2 在前端使用 AJAX
在前端脚本中使用 AJAX 进行请求:
jQuery(document).ready(function(('#my-button').on('click', function() {
wpdb;
wpdb->prefix . 'my_first_plugin_table';
wpdb->get_charset_collate();
table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
name tinytext NOT NULL,
value text NOT NULL,
PRIMARY KEY (id)
) sql);
}
register_activation_hook(__FILE__, 'my_first_plugin_create_db_table');
33.2 插入数据
在插件中插入数据到自定义表:
function my_first_plugin_insert_data(value) {
global table_name = wpdb->insert(
name,
'value' => wpdb;
wpdb->prefix . 'my_first_plugin_table';
wpdb->get_results("SELECT * FROM results;
}
设置测试环境: 创建 phpunit.xml.dist 文件以配置测试环境: <phpunit bootstrap="tests/bootstrap.php"> <testsuites> <testsuite name="My First Plugin Test Suite"> <directory>tests</directory> </testsuite> </testsuites> </phpunit>
编写测试: 在 tests 目录中创建测试文件,例如 test-sample.php: class SampleTest extends WP_UnitTestCase { public function test_sample() { email = sanitize_email(url = esc_url(_POST['_wpnonce'], 'my_action')) { die('Security check failed'); }
45.2 SQL 注入防护
使用 prepare 方法来防止 SQL 注入:
global wpdb->query(wpdb->posts WHERE post_title = %s", message = __('Hello, World!', 'my-first-plugin'); _e('Welcome to my plugin!', 'my-first-plugin');
生成 POT 文件: 使用 wp i18n 工具来生成 POT 文件: npx wp i18n make-pot . languages/my-first-plugin.pot
学习 WordPress 插件开发是一个非常有益且实用的技能,可以帮助你扩展和定制 WordPress 网站的功能。以下是一个详细的指南,帮助你从零开始学习 WordPress 插件开发。
1. 基础知识准备
在开始插件开发之前,你需要具备一些基本知识:
2. 设置开发环境
为插件开发设置一个合适的开发环境:
3. 了解 WordPress 插件结构
一个简单的 WordPress 插件通常包含以下文件和文件夹:
plugin-name.php
,包含插件的主要功能代码。4. 创建第一个插件
下面是创建一个简单插件的步骤:
4.1 创建插件目录和主文件
在
wp-content/plugins
目录下创建一个新文件夹,例如my-first-plugin
。在该文件夹中创建一个 PHP 文件,例如my-first-plugin.php
。4.2 插件头部信息
在
my-first-plugin.php
文件中添加插件的头部信息:4.3 插件的基本功能
添加一些基本功能,如在 WordPress 后台显示一个简单的信息:
5. 学习 WordPress 钩子(Hooks)
WordPress 插件开发的核心是钩子(Hooks),它包括动作钩子(Action Hooks)和过滤器钩子(Filter Hooks)。通过钩子,你可以在特定的时间点执行代码:
例子:
6. 学习 WordPress 插件 API
WordPress 提供了丰富的 API 供插件开发者使用:
7. 学习插件国际化和本地化
为了使你的插件可以被翻译成不同的语言,了解如何国际化和本地化插件是很重要的:
8. 探索插件开发资源
9. 配置插件设置页面
为插件添加一个设置页面是常见的需求。以下是如何使用 Settings API 创建一个简单的插件设置页面的步骤:
9.1 添加菜单项
首先,需要在 WordPress 管理菜单中添加一个新的菜单项:
9.2 创建设置页面
在回调函数
my_first_plugin_settings_page
中定义设置页面的内容:9.3 注册设置
使用 Settings API 注册插件设置:
10. 创建短代码
短代码允许用户在文章和页面中插入自定义内容。以下是如何创建一个简单的短代码:
11. 创建小工具
小工具可以在 WordPress 侧边栏等小工具区域显示内容。以下是如何创建一个简单的小工具:
“`php
class My_First_Plugin_Widget extends WP_Widget {
function construct() { parent::_construct( ‘my_first_plugin_widget’, // ID (‘My First Plugin Widget’, ‘text_domain’), // 名称
array(‘description’ => _(‘A simple widget’, ‘text_domain’)) // 描述
);
}
11. 创建小工具(续)
11.1 完成小工具的表单和更新方法
在上面的代码基础上,继续完成小工具的表单和更新方法:
13. 安全性和最佳实践
确保你的插件是安全的,并遵循最佳实践:
13.1 数据验证和清理
在处理用户输入时,确保对数据进行验证和清理:
13.2 使用非ces (Nonces) 进行安全验证
在处理表单提交时,使用非ces 来防止跨站请求伪造 (CSRF) 攻击:
13.3 避免直接文件访问
在插件的每个文件顶部添加以下代码,防止直接访问:
14. 插件国际化和本地化(续)
确保你的插件可以被翻译成不同的语言:
14.1 创建语言文件
在插件目录下创建一个
languages
文件夹,并使用.pot
文件保存插件的翻译字符串。例如,创建一个my-first-plugin.pot
文件。14.2 加载语言文件
在插件初始化时加载语言文件:
15. 发布和分发插件
当你完成插件开发后,可以考虑将插件发布到 WordPress 插件目录中。
15.1 准备插件
确保你的插件包含以下文件:
.pot
文件和翻译文件。15.2 创建 README 文件
使用 Markdown 编写 README 文件,并确保它包含以下部分:
15.3 提交插件
访问 WordPress 插件提交页面 并按照指南提交你的插件。一旦审核通过,你的插件将出现在 WordPress 插件目录中。
16. 进一步学习资源
要深入学习 WordPress 插件开发,以下资源非常有用:
16.1 官方文档
16.2 在线课程和教程
16.3 开发者社区
16.4 博客和文章
17. 高级插件开发技巧
17.1 面向对象编程 (OOP)
使用面向对象编程风格可以使你的插件代码更具可维护性和可扩展性。以下是一个简单的 OOP 插件示例:
17.2 使用命名空间
使用命名空间可以避免类名和函数名冲突:
17.3 自动加载
使用自动加载器可以简化类文件的加载:
17.4 单例模式
使用单例模式确保插件的主类只实例化一次:
19.2 插入数据
20. AJAX 操作
使用 AJAX 可以在不刷新页面的情况下与服务器进行交互。
20.1 在前端调用 AJAX
21. 使用自定义钩子和过滤器
创建自定义钩子和过滤器,使其他开发者可以扩展你的插件功能。
21.1 创建自定义动作钩子
21.2 创建自定义过滤器
22. 使用第三方库
有时,你可能需要在插件中使用第三方库。你可以通过 Composer 来管理依赖关系。
22.1 安装 Composer
确保在你的开发环境中安装了 Composer。
22.2 创建
composer.json
文件在插件根目录下创建一个
composer.json
文件:22.3 安装依赖
在终端中运行以下命令:
22.4 在插件中加载 Composer 自动加载器
在插件的主文件中添加以下代码:
23. 测试和调试(续)
23.1 使用 WP_DEBUG
在
wp-config.php
文件中启用调试模式:此设置会将错误记录到
wp-content/debug.log
文件中,而不是直接显示在页面上。23.2 使用 PHPStorm 和 Xdebug 进行调试
php.ini
文件:zend_extension="path/to/xdebug.so" xdebug.remote_enable=1 xdebug.remote_host=127.0.0.1 xdebug.remote_port=9000 xdebug.remote_handler=dbgp
24. 国际化与本地化
24.1 准备插件以进行翻译
使用
__()
和_e()
函数准备你的插件代码:24.2 创建 POT 文件
使用
xgettext
或 Poedit 等工具生成 POT 文件:wp i18n
工具来生成 POT 文件:npx wp i18n make-pot . languages/my-first-plugin.pot
47. 优化性能
47.1 缓存
wp_cache_set
和wp_cache_get
进行对象缓存:wp_cache_set('my_cache_key',
cached_data = wp_cache_get('my_cache_key');
47.2 优化数据库查询
确保数据库查询高效,避免不必要的查询和数据加载:
50.2 处理多站点特定功能
get_site_option
和update_site_option
来存储和检索全局设置:function my_first_plugin_get_global_setting(
key); } function my_first_plugin_set_global_setting(
value) { update_site_option(
value); }
switch_to_blog
和restore_current_blog
函数在不同站点之间切换,以同步数据:function my_first_plugin_sync_data_across_sites(
wpdb;
wpdb->get_col("SELECT blog_id FROM
blog_ids as
blog_id); update_option('my_first_plugin_data',
this->assertTrue(true); } }
vendor/bin/phpunit
52. 钩子和过滤器
52.1 创建自定义钩子
do_action('my_first_plugin_custom_action',
arg2);
52.2 使用钩子和过滤器
add_action
函数来挂载自定义动作钩子:add_action('my_first_plugin_custom_action', 'my_custom_action_function', 10, 2); function my_custom_action_function(
arg2) { // 自定义动作处理逻辑 }
add_filter
函数来挂载自定义过滤器钩子:add_filter('my_first_plugin_custom_filter', 'my_custom_filter_function', 10, 3); function my_custom_filter_function(
arg1,
value; }