注册分类
在注册功能之前,您必须至少注册一个分类。分类有助于组织功能,使其更易于发现、过滤。
函数签名
wp_register_ability_category( string $slug, array $args ): ?\WP_Ability_Category参数:
$slug(string):分类的唯一标识符。仅可包含小写字母数字字符和连字符(不可包含下划线或大写字母)。$args(array):包含以下键的分类配置:label(string,必填):分类的人类可读名称。应支持翻译。description(string,必填):分类用途的详细描述。应支持翻译。meta(array,可选):用于存储关于分类的任意附加元数据的关联数组。
返回值: (?\WP_Ability_Category) 如果成功注册,则返回已注册分类的实例;如果失败(例如参数无效、slug 重复),则返回 null。
注意: 必须在 wp_abilities_api_categories_init 动作钩子期间注册分类。
代码示例
add_action( 'wp_abilities_api_categories_init', 'wporg_register_categories' );
/**
* Register custom ability categories.
*
* @return void
*/
function wporg_register_categories() {
wp_register_ability_category(
'data-retrieval',
array(
'label' => __( 'Data Retrieval', 'textdomain' ),
'description' => __( 'Abilities that retrieve and return data from the WordPress site.', 'textdomain' ),
)
);
wp_register_ability_category(
'data-modification',
array(
'label' => __( 'Data Modification', 'textdomain' ),
'description' => __( 'Abilities that modify data on the WordPress site.', 'textdomain' ),
)
);
wp_register_ability_category(
'communication',
array(
'label' => __( 'Communication', 'textdomain' ),
'description' => __( 'Abilities that send messages or notifications.', 'textdomain' ),
)
);
}分类 Slug 命名规范
$slug 参数必须遵循以下规则:
- 格式: 仅可包含小写字母数字字符 (
a-z,0-9) 和连字符 (-)。 - 有效示例:
data-retrieval,ecommerce,site-information,user-management,category-123 - 无效示例:
- 大写:
Data-Retrieval,MyCategory - 下划线:
data_retrieval - 特殊字符:
data.retrieval,data/retrieval,data retrieval - 首尾连字符:
-data,data- - 双连字符:
data--retrieval
注销分类
移除已注册的分类。
函数签名
wp_unregister_ability_category( string $slug ) ?\WP_Ability_Category参数:
$slug(string):已注册分类的 slug。
返回值: (?\WP_Ability_Category) 如果成功,则返回注销后的分类实例;如果失败,则返回 null。
获取分类
通过 slug 检索特定分类。
函数签名
wp_get_ability_category( string $slug ) ?\WP_Ability_Category参数:
$slug(string):已注册分类的 slug。
返回值: (?\WP_Ability_Category) 如果成功,则返回分类实例;如果失败,则返回 null。
获取所有分类
获取所有已注册分类,以 slug 为键的关联数组形式返回。
函数签名
wp_get_ability_categories() array返回值: (array) 所有已注册分类的关联数组,以 slug 为键。每个值均为 WP_Ability_Category 类的实例。
注册功能 (wp_register_ability)
向 Abilities API 添加功能的主要方式是使用 wp_register_ability() 函数,通常将其挂钩到 wp_abilities_api_init 动作中。
函数签名
wp_register_ability( string $name, array $args ): ?\WP_Ability参数:
$name(string):功能的唯一标识符。$args(array):定义功能配置的参数字典。- 返回值: (
?\WP_Ability) 如果成功注册,则返回已注册功能的实例;如果失败(例如参数无效、ID 重复),则返回null。
参数详解
$args 数组接受以下键:
label(string,必填):功能的人类可读名称。用于显示目的。应支持翻译。description(string,必填):关于功能作用、目的及其参数或返回值的详细描述。这对于 AI 代理理解如何使用及何时使用该功能至关重要。应支持翻译。category(string,必填):该功能所属分类的 slug。在使用wp_register_ability_category()注册功能之前,必须先注册该分类。分类有助于按用途组织和过滤功能。详情见 注册分类。input_schema(array,可选):描述能力执行回调预期输入参数的 JSON Schema 定义。仅在创建需要输入的 Abilities 时需要。未提供 schema 时默认为null。用于验证和文档说明。output_schema(array,必填):描述能力返回数据预期格式的 JSON Schema 定义。用于验证和文档说明。execute_callback(callable,必填):调用此功能时执行的 PHP 函数或方法。- 回调接收一个可选参数,即能力的输入数据。当定义了输入 schema 时,该参数是必需的。
- 输入参数的类型将与 input_schema 中定义的相同(例如
array,object,string等)。 - 回调应返回功能操作的结果,或在失败时返回
WP_Error对象。 permission_callback(callable,必填):检查当前用户是否有权限执行此功能的回调函数。- 回调接收一个可选参数,即能力的输入数据。当定义了输入 schema 时,该参数是必需的。
- 输入参数的类型将与 input_schema 中定义的相同(例如
array,object,string等)。 - 回调应返回布尔值(如果用户有权限则为
true,否则为false),或在失败时返回WP_Error对象。 - 如果设置了输入 schema 且输入不符合输入 schema 的验证,将不会调用权限回调,而是直接返回
WP_Error。 meta(array,可选):用于存储关于功能的任意附加元数据的关联数组。annotations(array,可选):提供关于功能行为特征的提示信息的关联数组。支持以下键:instructions(string,可选):使用功能的自定义指令或指导(默认值:'')。readonly(boolean,可选):表示该功能是否仅读取数据而不修改其环境(默认值:false)。destructive(boolean,可选):表示该功能是否可能对其环境执行破坏性更新。如果为true,则该功能可能执行任何类型的修改,包括删除或其他破坏性更改。如果为false,则该功能仅执行添加性更新(默认值:true)。idempotent(boolean,可选):表示使用相同参数多次调用该功能是否对其环境没有额外影响(默认值:false)。
show_in_rest (boolean, 可选): 是否通过 REST API 暴露此能力。默认值:false。- 当值为
true时,该能力将列在 REST API 响应中,并可通过 REST 端点执行。 - 当值为
false时,该能力将从 REST API 列表中隐藏,无法通过 REST 端点执行,但仍可用于内部 PHP 调用。
ability_class (string, 可选): 自定义能力类的完全限定类名,该类需扩展 WP_Ability。这允许您通过扩展基础 WP_Ability 类并重写其方法来定制能力的行为。自定义类必须扩展 WP_Ability。默认值:WP_Ability。能力命名约定
$name 参数必须遵循 namespace/ability-name 模式:
- 格式: 只能包含小写字母数字字符(
a-z,0-9)、连字符(-)以及一个用于命名的正斜杠(/)。 - 约定: 使用插件标识符作为命名空间,例如
wporg/ability-name。 - 示例:
wporg/update-settings、woocommerce/get-product、contact-form/send-message、analytics/track-event
代码示例
注册不带输入模式的数据检索能力
add_action( 'wp_abilities_api_init', 'wporg_register_site_info_ability' );
/**
* 注册 'wporg/get-site-info' 能力。
*
* @return void
*/
function wporg_register_site_info_ability() {
wp_register_ability(
'wporg/get-site-info',
array(
'label' => __( '获取站点信息', 'textdomain' ),
'description' => __( '检索有关 WordPress 站点的基本信息,包括名称、描述和 URL。', 'textdomain' ),
'category' => 'data-retrieval',
'output_schema' => array(
'type' => 'object',
'properties' => array(
'name' => array(
'type' => 'string',
'description' => '站点名称',
),
'description' => array(
'type' => 'string',
'description' => '站点标语',
),
'url' => array(
'type' => 'string',
'format' => 'uri',
'description' => '站点 URL',
),
),
),
'execute_callback' => function () {
return array(
'name' => get_bloginfo( 'name' ),
'description' => get_bloginfo( 'description' ),
'url' => home_url(),
);
},
'permission_callback' => '__return_true',
'meta' => array(
'annotations' => array(
'readonly' => true,
'destructive' => false,
),
),
)
);
}注册带输入参数的能力
add_action( 'wp_abilities_api_init', 'wporg_register_update_option_ability' );
/**
* 注册 'wporg/update-option' 能力。
*
* @return void
*/
function wporg_register_update_option_ability() {
wp_register_ability(
'wporg/update-option',
array(
'label' => __( '更新 WordPress 选项', 'textdomain' ),
'description' => __( '更新数据库中 WordPress 选项的值。需要 manage_options 权限。', 'textdomain' ),
'category' => 'data-modification',
'input_schema' => array(
'type' => 'object',
'properties' => array(
'option_name' => array(
'type' => 'string',
'description' => '要更新的选项名称',
'minLength' => 1,
),
'option_value' => array(
'description' => '选项的新值',
),
),
'required' => array( 'option_name', 'option_value' ),
'additionalProperties' => false,
),
'output_schema' => array(
'type' => 'object',
'properties' => array(
'success' => array(
'type' => 'boolean',
'description' => '选项是否成功更新',
),
'previous_value' => array(
'description' => '选项的先前值',
),
),
),
'execute_callback' => function ( $input ) {
$option_name = $input['option_name'];
$new_value = $input['option_value'];
$previous_value = get_option( $option_name );
$success = update_option( $option_name, $new_value );
return array(
'success' => $success,
'previous_value' => $previous_value,
);
},
'permission_callback' => function () {
return current_user_can( 'manage_options' );
},
'meta' => array(
'annotations' => array(
'destructive' => false,
'idempotent' => true,
),
),
)
);
}注册带插件依赖的能力
add_action( 'wp_abilities_api_init', 'woo_register_woo_stats_ability' );
/**
* 注册 WooCommerce 统计能力。
*
* @return void
*/
function woo_register_woo_stats_ability() {
// 仅当 WooCommerce 激活时才注册。
if ( ! class_exists( 'WooCommerce' ) ) {
return;
}
wp_register_ability(
'woo/get-woo-stats',
array(
'label' => __( '获取 WooCommerce 统计数据', 'textdomain' ),
'description' => __( '检索基本的 WooCommerce 商店统计数据,包括总订单量和收入。', 'textdomain' ),
'category' => 'ecommerce',
'input_schema' => array(
'type' => 'object',
'properties' => array(
'period' => array(
'type' => 'string',
'enum' => array( 'today', 'week', 'month', 'year' ),
'default' => 'month',
'description' => '统计数据的时间周期',
),
),
'additionalProperties' => false,
),
'output_schema' => array(
'type' => 'object',
'properties' => array(
'total_orders' => array(
'type' => 'integer',
'description' => '周期内的订单数量',
),
'total_revenue' => array(
'type' => 'number',
'description' => '周期内的总收入',
),
),
),
'execute_callback' => function ( $input ) {
$period = $input['period'] ?? 'month';
// 实现将根据周期计算统计数据。
return array(
'total_orders' => 42,
'total_revenue' => 1250.50,
);
},
'permission_callback' => function () {
return current_user_can( 'manage_woocommerce' );
},
'meta' => array(
'requires_plugin' => 'woocommerce',
),
)
);
}注册可能失败的能力
add_action( 'wp_abilities_api_init', 'wporg_register_send_email_ability' );
/**
* 注册 'wporg/send-email' 能力。
*
* @return void
*/
function wporg_register_send_email_ability() {
wp_register_ability(
'wporg/send-email',
array(
'label' => __( '发送邮件', 'textdomain' ),
'description' => __( '使用 WordPress 邮件功能向指定收件人发送邮件。', 'textdomain' ),
'category' => 'communication',
'input_schema' => array(
'type' => 'object',
'properties' => array(
'to' => array(
'type' => 'string',
'format' => 'email',
'description' => '收件人电子邮件地址',
),
'subject' => array(
'type' => 'string',
'minLength' => 1,
'description' => '电子邮件主题',
),
'message' => array(
'type' => 'string',
'minLength' => 1,
'description' => '电子邮件正文',
),
),
'required' => array( 'to', 'subject', 'message' ),
'additionalProperties' => false,
),
'output_schema' => array(
'type' => 'object',
'properties' => array(
'sent' => array(
'type' => 'boolean',
'description' => '邮件是否成功发送',
),
),
),
'execute_callback' => function ( $input ) {
$sent = wp_mail(
$input['to'],
$input['subject'],
$input['message']
);
if ( ! $sent ) {
return new \WP_Error(
'email_send_failed',
sprintf( __( '发送邮件失败' ), 'textdomain' )
);
}
return array( 'sent' => true );
},
'permission_callback' => function () {
return current_user_can( 'publish_posts' );
},
)
);
}使用自定义能力类注册能力
ability_class 参数允许您使用扩展自 WP_Ability 的自定义类。当您需要扩展基础 WP_Ability 类的默认行为时,这非常有用。
示例:创建带有额外方法的自定义能力类
/**
* 添加日志记录的自定义能力类。
*
* 本示例展示了如何扩展 WP_Ability 以添加自定义行为,
* 同时仍利用所有标准的能力功能。
*/
class WPOrg_Post_Validator_Ability extends WP_Ability {
/**
* 重写 do_execute 方法以添加自定义日志记录。
*
* 这演示了如何覆盖 WP_Ability 中的方法来定制标准执行之前或之后的行为。
*
* @param mixed $input 可选。能力的输入数据。
* @return mixed|\WP_Error 能力执行的结果。
*/
protected function do_execute( $input = null ) {
// 为调试目的记录执行过程。
error_log(
sprintf(
'Executing ability: %s with input: %s',
$this->get_name(),
json_encode( $input )
)
);
// 调用父级的 do_execute 以运行正常的 execute_callback。
$result = parent::do_execute( $input );
// 记录结果
if ( is_wp_error( $result ) ) {
error_log(
sprintf(
'Ability %s failed: %s',
$this->get_name(),
$result->get_error_message()
)
);
} else {
error_log(
sprintf(
'Ability %s completed successfully',
$this->get_name()
)
);
}
return $result;
}
}
/**
* 使用自定义能力类注册能力。
*/
add_action( 'wp_abilities_api_init', 'wporg_register_post_validator_ability' );
function wporg_register_post_validator_ability() {
wp_register_ability(
'wporg/validate-post',
array(
'label' => __( '验证文章', 'textdomain' ),
'description' => __( '验证文章是否存在、已发布并返回其元数据。', 'textdomain' ),
'category' => 'data-retrieval',
'input_schema' => array(
'type' => 'object',
'properties' => array(
'post_id' => array(
'type' => 'integer',
'description' => '要验证的文章 ID',
'minimum' => 1,
),
),
'required' => array( 'post_id' ),
'additionalProperties' => false,
),
'output_schema' => array(
'type' => 'object',
'properties' => array(
'valid' => array(
'type' => 'boolean',
'description' => '文章是否有效',
),
'post_title' => array(
'type' => 'string',
'description' => '文章标题',
),
'post_date' => array(
'type' => 'string',
'description' => '文章发布日期',
),
),
),
'execute_callback' => function ( $input ) {
$post_id = $input['post_id'];
$post = get_post( $post_id );
if ( ! $post ) {
return new \WP_Error(
'invalid_post',
__( '指定的文章不存在。', 'textdomain' )
);
}
// 检查文章是否已发布
if ( 'publish' !== $post->post_status ) {
return new \WP_Error(
'post_not_published',
__( '指定的文章未发布。', 'textdomain' )
);
}
// 如果验证通过,返回文章信息
return array(
'valid' => true,
'post_title' => $post->post_title,
'post_date' => $post->post_date,
);
},
'permission_callback' => function () {
// 任何登录用户都可以验证文章
return is_user_logged_in();
},
'meta' => array(
'annotations' => array(
'readonly' => true,
'destructive' => false,
),
),
// 指定要使用的自定义能力类
'ability_class' => 'WPOrg_Post_Validator_Ability',
)
);
}关于自定义能力类的重要说明:
- 您的自定义类必须扩展
WP_Ability - 自定义类仅用于实例化能力——
ability_class参数不作为能力的属性存储 - 您可以覆盖受保护的方法,如
do_execute()、validate_input()或validate_output()来自定义行为 - 您可以添加自定义方法以提供针对您能力的特定额外功能
- 自定义类在其构造函数中接收与基础
WP_Ability类相同的$name和$args参数 - 如果指定的类不存在或未扩展
WP_Ability,注册将失败并显示_doing_it_wrong()通知
检查能力是否已注册
您可以使用 wp_has_ability() 函数检查能力是否已注册。
函数签名
wp_has_ability( string $name ): bool参数:
$name(string):要检查的能力名称(命名空间/能力名称)。
返回: (bool) 如果能力已注册则为 true,否则为 false。
代码示例
$ability_name = 'wporg/get-site-info';
if ( wp_has_ability( $ability_name ) ) {
// 能力已注册
}使用能力 (wp_get_ability, wp_get_abilities)
一旦能力被注册,就可以使用 Abilities API 的全局函数来获取和执行它们。
获取特定能力 (wp_get_ability)
要通过其名称(命名空间/能力名称)获取单个能力对象:
/**
* 使用 Abilities API 检索已注册的 Ability。
*
* @param string $name 已注册 Ability 的名称,包含其命名空间。
* @return ?WP_Ability 已注册的 Ability 实例,如果未注册则返回 null。
*/
function wp_get_ability( string $name ): ?WP_Ability
// 示例:
$site_info_ability = wp_get_ability( 'wporg/get-site-info' );
if ( $site_info_ability ) {
// Ability 存在且已注册。
$site_info = $site_info_ability->execute();
if ( is_wp_error( $site_info ) ) {
// 处理 WP_Error。
echo '错误:' . $site_info->get_error_message();
} else {
// 使用 $site_info 数组。
echo '站点名称:' . $site_info['name'];
}
} else {
// 未找到或未注册该 Ability。
}获取所有已注册的 Abilities (wp_get_abilities)
要获取所有已注册 abilities 的数组:
/**
* 使用 Abilities API 检索所有已注册的 abilities。
*
* @return WP_Ability[] 已注册 abilities 的数组。
*/
function wp_get_abilities(): array
// 示例:获取所有已注册的 abilities
$all_abilities = wp_get_abilities();
foreach ( $all_abilities as $name => $ability ) {
echo 'Ability 名称:' . esc_html( $ability->get_name() ) . "\n";
echo '标签:' . esc_html( $ability->get_label() ) . "\n";
echo '描述:' . esc_html( $ability->get_description() ) . "\n";
echo "---\n";
}执行 Ability ($ability->execute())
一旦你获得了 WP_Ability 对象(通常来自 wp_get_ability),你可以使用 execute() 方法来执行它。
/**
* 在输入验证和权限检查后执行 Ability。
*
* @param mixed $input 可选。Ability 的输入数据。默认为 `null`。
* @return mixed|WP_Error Ability 执行的结果,失败时返回 WP_Error。
*/
// public function execute( $input = null )
// 示例 1:无输入参数的 Ability
$ability = wp_get_ability( 'wporg/get-site-info' );
if ( $ability ) {
$site_info = $ability->execute(); // 不需要输入
if ( is_wp_error( $site_info ) ) {
// 处理 WP_Error
echo '错误:' . $site_info->get_error_message();
} else {
// 使用 $site_info 数组
echo '站点名称:' . $site_info['name'];
}
}
// 示例 2:带输入参数的 Ability
$ability = wp_get_ability( 'wporg/update-option' );
if ( $ability ) {
$input = array(
'option_name' => 'blogname',
'option_value' => '我的更新后的站点名称',
);
$result = $ability->execute( $input );
if ( is_wp_error( $result ) ) {
// 处理 WP_Error
echo '错误:' . $result->get_error_message();
} else {
// 使用 $result
if ( $result['success'] ) {
echo '选项已成功更新!';
echo '之前的值:' . $result['previous_value'];
}
}
}
// 示例 3:带复杂输入验证的 Ability
$ability = wp_get_ability( 'wporg/send-email' );
if ( $ability ) {
$input = array(
'to' => 'user@example.com',
'subject' => '来自 WordPress 的问候',
'message' => '这是来自 Abilities API 的测试消息。',
);
$result = $ability->execute( $input );
if ( is_wp_error( $result ) ) {
// 处理 WP_Error
echo '错误:' . $result->get_error_message();
} elseif ( $result['sent'] ) {
echo '邮件发送成功!';
} else {
echo '邮件发送失败。';
}
}检查权限 ($ability->check_permissions())
你可以检查当前用户是否有权限执行该 Ability,而无需实际执行它。check_permissions() 方法返回 true、false 或 WP_Error 对象。true 表示授予权限,false 表示用户仅仅缺乏权限,而 WP_Error 返回值通常表示权限检查过程失败(如内部错误或配置不当)。你必须使用 is_wp_error() 来正确处理错误,并区分权限拒绝和实际错误:
$ability = wp_get_ability( 'wporg/update-option' );
if ( $ability ) {
$input = array(
'option_name' => 'blogname',
'option_value' => '新站点名称',
);
// 在执行前检查权限 - 始终先使用 is_wp_error()
$has_permissions = $ability->check_permissions( $input );
if ( true === $has_permissions ) {
// 已授予权限 – 可以安全执行。
echo '您有权限执行此 Ability。';
} else {
// 不要向未认证的用户泄露权限错误。
if ( is_wp_error( $has_permissions ) ) {
error_log( '权限检查失败:' . $has_permissions->get_error_message() );
}
echo '您没有权限执行此 Ability。';
}
}检查 Ability 属性
WP_Ability 类提供了多个 getter 方法来检查 Ability 的属性:
$ability = wp_get_ability( 'wporg/get-site-info' );
if ( $ability ) {
// 基本属性
echo '名称:' . $ability->get_name() . "\n";
echo '标签:' . $ability->get_label() . "\n";
echo '描述:' . $ability->get_description() . "\n";
// Schema 信息
$input_schema = $ability->get_input_schema();
$output_schema = $ability->get_output_schema();
echo '输入 Schema: ' . json_encode( $input_schema, JSON_PRETTY_PRINT ) . "\n";
echo '输出 Schema: ' . json_encode( $output_schema, JSON_PRETTY_PRINT ) . "\n";
// 元数据
$meta = $ability->get_meta();
if ( ! empty( $meta ) ) {
echo '元数据:' . json_encode( $meta, JSON_PRETTY_PRINT ) . "\n";
}
}错误处理模式
Abilities API 使用了多种错误处理机制:
$ability = wp_get_ability( 'wporg/some-ability' );
if ( ! $ability ) {
// Ability 未注册
echo '未找到 Ability';
return;
}
$result = $ability->execute( $input );
// 检查 WP_Error(验证、权限或回调错误)
if ( is_wp_error( $result ) ) {
echo 'WP_Error: ' . $result->get_error_message();
return;
}
// 检查 null 结果(权限被拒、无效回调或验证失败)
if ( is_null( $result ) ) {
echo '执行返回 null - 请检查权限和回调有效性';
return;
}
// 成功 - 使用结果
// 根据 Ability 的输出 Schema 处理 $result