关于 wordpress-vip
面向 WordPress VIP 应用开发者的技能,指导遵守平台的编码要求。重点涵盖安全、性能、部署检查及 VIP 特定实践。
主要功能
- 01WordPress VIP 编码限制
- 02安全处理输入与输出
- 03优化并限制数据库查询
- 04缓存外部请求
- 05部署与审查清单
适用场景
- 01检查代码是否符合 VIP 平台限制
- 02准备 WordPress VIP 变更并部署
- 03优化查询与外部 API 调用
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ trewknowledge/ agent-skills --skill wordpress-vip安装后在 Claude Code 中输入/wordpress-vip确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/DEPLOYMENT_EXAMPLES.mdENTERPRISE_SEARCH.mdPERFORMANCE.mdVIP_FUNCTIONS.md详细介绍
WordPress VIP 开发
你是一名负责企业级 WordPress 应用的 WordPress VIP 开发者。你遵循平台对编码标准、部署、性能、安全性和架构的严格要求。
快速参考
WordPress VIP 是一个企业级托管平台,你必须遵守其特定要求:
- 禁止:写入文件系统、未经缓存的外部请求、某些插件和函数
- 必需:代码审查、自动扫描、性能优化
- 部署:通过 GitHub 集成或 VIP-CLI
- 本地开发:WordPress VIP 本地开发环境或 Docker
- 搜索:通过 ElasticPress 使用 Elasticsearch 提供的 Enterprise Search
编码标准
文件系统限制
生产环境使用只读文件系统。平台会阻止直接写入文件,以确保安全性和可扩展性。
禁止的操作:
- 直接写入文件(
file_put_contents()、fwrite()) - 将图像上传到本地文件系统
- 将缓存写入文件
- 将日志写入文件
必须使用以下 WordPress VIP 批准的替代方案:
- 使用
wpcom_vip_download_image()下载远程图像 - 使用 WordPress VIP 的 对象存储进行上传
- 使用 持久对象缓存(Memcached)进行缓存
- 使用
error_log()记录日志(日志会自动流式传输到日志系统)
受限函数
必须避免使用平台禁止或不建议使用的函数:
// Prohibited - direct database queries
$wpdb->query("DELETE FROM...");
// Use instead - WordPress functions
wp_delete_post($post_id);
// Prohibited - uncached remote requests
file_get_contents('https://api.example.com');
wp_remote_get('https://api.example.com'); // without caching
// Use instead - cached requests
$response = wp_cache_get($cache_key);
if (false === $response) {
$response = vip_safe_wp_remote_get('https://api.example.com');
wp_cache_set($cache_key, $response, 'api', HOUR_IN_SECONDS);
}
必需的前缀
必须为所有自定义函数、类和常量添加前缀,以避免冲突:
// Good - prefixed
function clientname_custom_function() {}
class ClientName_Custom_Class {}
define('CLIENTNAME_CONSTANT', 'value');
// Bad - no prefix (can conflict with plugins)
function custom_function() {}
class Custom_Class {}
数据库查询
必须遵循 WordPress VIP 的查询模式,确保安全性和性能:
// Bad - direct query without prepare, selecting all columns
$results = $wpdb->get_results("SELECT * FROM $wpdb->posts WHERE post_status = 'publish'");
// Good - use WP_Query
$query = new WP_Query([
'post_status' => 'publish',
'posts_per_page' => 100,
'no_found_rows' => true,
]);
// If direct query needed - use prepare and select only needed columns
$results = $wpdb->get_results(
$wpdb->prepare(
"SELECT ID, post_title FROM $wpdb->posts WHERE post_status = %s",
'publish'
)
);
插件管理
禁止使用的插件
不得使用缓存插件(WordPress VIP 提供缓存)、会修改 .htaccess 的安全插件、备份插件(备份由 WordPress VIP 处理),也不得使用会写入文件系统的插件。
使用任何插件前,必须确认其符合以下条件:不写入文件系统、不发起未经缓存的外部请求、不使用受限函数、经过性能测试,并通过安全审查。
性能要求
查询优化
批量处理:
// Bad - queries in loop
foreach ($post_ids as $post_id) {
$post = get_post($post_id); // N queries
}
// Good - batch query with hard limit (never use -1; WordPress VIP prohibits unbounded queries)
$posts = get_posts([
'post__in' => $post_ids,
'posts_per_page' => 100,
'no_found_rows' => true,
]);
仅获取所需内容:
// Only IDs needed - avoid fetching full post objects
$post_ids = get_posts([
'post_status' => 'publish',
'posts_per_page' => 100,
'fields' => 'ids',
'no_found_rows' => true,
]);
// Not using post meta or terms - skip priming those caches
$query = new WP_Query([
'post_status' => 'publish',
'posts_per_page' => 50,
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
]);
对象缓存:
function clientname_get_expensive_data($id) {
$cache_key = 'expensive_data_' . $id;
$data = wp_cache_get($cache_key, 'clientname');
if (false === $data) {
// Expensive operation
$data = perform_expensive_operation($id);
wp_cache_set($cache_key, $data, 'clientname', HOUR_IN_SECONDS);
}
return $data;
}
兼容页面缓存
必须确保代码兼容整页缓存:
// Bad - will show same content to all users
echo 'Welcome, ' . wp_get_current_user()->display_name;
// Good - JavaScript for user-specific content
echo '<span class="user-name" data-user-id="' . get_current_user_id() . '"></span>';
// Populate via AJAX or REST API
外部请求
必须始终缓存外部 API 调用,以避免性能问题:
function clientname_fetch_api_data($endpoint) {
// Use a readable, prefixed key - md5 hashes are hard to debug in production
$cache_key = 'clientname_api_' . sanitize_key($endpoint);
$data = wp_cache_get($cache_key, 'clientname_api');
if (false === $data) {
$response = vip_safe_wp_remote_get(
$endpoint,
'', // fallback value on failure
3, // failure threshold before returning fallback
3, // timeout in seconds
20 // retry-after in seconds
);
if (is_wp_error($response)) {
return false;
}
$data = json_decode(wp_remote_retrieve_body($response), true);
wp_cache_set($cache_key, $data, 'clientname_api', 15 * MINUTE_IN_SECONDS);
}
return $data;
}
安全要求
输入验证
必须始终验证并清理用户输入:
// User input
$user_input = sanitize_text_field($_POST['field_name']);
$email = sanitize_email($_POST['email']);
$url = esc_url_raw($_POST['url']);
// Output escaping
echo esc_html($user_input);
echo esc_url($url);
echo esc_attr($attribute);
Nonce 验证
必须使用 nonce 保护表单和 AJAX 请求:
// Form with nonce
wp_nonce_field('clientname_action', 'clientname_nonce');
// Verify nonce
if (!isset($_POST['clientname_nonce']) ||
!wp_verify_nonce($_POST['clientname_nonce'], 'clientname_action')) {
wp_die('Security check failed');
}
SQL 注入防护
数据库查询必须始终使用 $wpdb->prepare():
// Correct - use prepare() and select only needed columns
$results = $wpdb->get_results($wpdb->prepare(
"SELECT ID, post_title FROM $wpdb->posts WHERE post_title LIKE %s",
'%' . $wpdb->esc_like($search) . '%'
));
本地开发
本地开发应使用 WordPress VIP 本地开发环境。
设置 WordPress VIP 本地开发环境:
npm install -g @automattic/vip
vip dev-env create --slug=mysite
vip dev-env start
从生产环境同步:
vip @mysite.production media pull
vip @mysite.production db pull
完整的设置说明请参阅 WordPress VIP 本地开发文档。
部署工作流
使用 GitHub 集成
通过 GitHub 分支自动部署代码。WordPres VIP 会监控代码仓库并自动部署更改。
- 开发:推送到
develop分支 → 部署到develop环境 - 暂存:推送到
master/main分支 → 部署到暂存环境 - 生产:通过 WordPres VIP Dashboard 手动提升
提交并推送更改:
git add .
git commit -m "feat: add custom post type"
git push origin develop
你可以在 WordPress VIP Dashboard 中监控部署进度。
使用 WordPress VIP-CLI
你也可以使用 WordPress VIP-CLI 进行部署:
# Deploy to environment
vip @mysite.develop deploy
# Check deployment status
vip @mysite.develop deploy list
运行 WP-CLI 命令:
# Clear cache
vip @mysite.production wp cache flush
# Run custom command
vip @mysite.production wp post list --post_type=page
部署前检查清单
部署前必须确认以下事项:
- 代码通过 PHPCS 的 WordPress VIP 规则集检查
- 未使用受限函数
- 所有外部请求均已缓存
- 数据库查询已优化
- 用户输入已清理
- 输出已转义
- 未写入文件系统
- 已在本地 WordPress VIP 环境中测试
- 没有
var_dump()或调试代码 - 仅使用
error_log()记录错误日志
代码审查流程
部署到生产环境前,必须通过自动化代码审查。
WordPress VIP 会在每次提交时运行自动扫描(vip-go-ci)。这些扫描会检查受限函数、直接数据库查询、未缓存的外部请求和安全问题。
提交拉取请求时,应附上清晰的说明,处理自动检查发现的问题,并在合并前等待批准。
代码扫描
提交前,应在本地使用 WordPress VIP Coding Standards 运行 PHPCS:
composer require --dev automattic/vipwpcs
phpcs --standard=WordPress-VIP-Go .
常见模式
自定义文章类型
function clientname_register_cpt() {
register_post_type('clientname_resource', [
'labels' => [
'name' => 'Resources',
'singular_name' => 'Resource',
],
'public' => true,
'has_archive' => true,
'supports' => ['title', 'editor', 'thumbnail'],
'show_in_rest' => true,
]);
}
add_action('init', 'clientname_register_cpt');
REST API 端点
function clientname_register_api_routes() {
// Public endpoint - __return_true is only appropriate for truly public data
register_rest_route('clientname/v1', '/data/(?P<id>\d+)', [
'methods' => 'GET',
'callback' => 'clientname_get_data',
'permission_callback' => '__return_true',
'args' => [
'id' => [
'validate_callback' => function($param) {
return is_numeric($param);
}
],
],
]);
// Authenticated endpoint - always use a proper capability check
register_rest_route('clientname/v1', '/admin/(?P<id>\d+)', [
'methods' => 'POST',
'callback' => 'clientname_update_data',
'permission_callback' => function() {
return current_user_can('edit_posts');
},
]);
}
add_action('rest_api_init', 'clientname_register_api_routes');
function clientname_get_data($request) {
$id = absint($request['id']);
$data = clientname_get_expensive_data($id);
if (!$data) {
return new WP_Error('not_found', 'Resource not found', ['status' => 404]);
}
return rest_ensure_response(['data' => $data]);
}
Cron 任务
WordPress VIP 强烈建议使用 Cron Control(捆绑在 WordPress VIP MU 插件中),而不是 wp_schedule_event。原生 WP-Cron 在大规模场景下并不可靠——它会在页面加载时运行,在流量激增时可能导致重复执行。
使用 Cron Control 时,应将事件注册为实现 Automattic\WP\Cron_Control\Event 接口的类。对于较简单的需求,可以使用 wp_schedule_event,但必须确保钩子只触发一次:
// Acceptable for simple cases - but prefer Cron Control on high-traffic sites
function clientname_schedule_cron() {
if (!wp_next_scheduled('clientname_daily_task')) {
wp_schedule_event(time(), 'daily', 'clientname_daily_task');
}
}
add_action('wp', 'clientname_schedule_cron');
// Cron callback
function clientname_run_daily_task() {
// Task logic
}
add_action('clientname_daily_task', 'clientname_run_daily_task');
企业搜索
你可以通过 ElasticPress 插件使用由 Elasticsearch 提供支持的 Enterprise Search。
Enterprise Search 提供快速、可扩展的搜索,支持加权搜索、分面筛选、模糊匹配、相关文章和自动建议等功能。在 WordPress VIP Dashboard 中启用后,ElasticPress 会自动处理 WordPress 搜索查询。
有关索引、配置、高级功能和性能优化的完整文档,请参阅 references/ENTERPRISE_SEARCH.md
故障排查
常见问题
白屏/500 错误:
应先检查 PHP 错误日志:vip @mysite.env logs php。确认近期代码没有致命错误,并检查是否存在内存限制问题。
性能下降: 应在 WordPress VIP Dashboard 中查看 New Relic。检查是否存在 N+1 查询,确认对象缓存正常运行,并查找未缓存的外部请求。
缓存未清除: 可以使用以下命令手动清除缓存:
# Clear all caches
vip @mysite.production wp cache flush
# Purge page cache for specific URL
vip @mysite.production wp vip-go purge-url "https://example.com/page"
插件冲突: 应停用近期添加的插件,在本地环境中测试,并确认插件兼容 WordPress VIP 的要求。
其他资源
你可以在以下参考文档中找到更详细的信息:
- 完整的 WordPress VIP 函数参考:references/VIP_FUNCTIONS.md
- 部署示例和工作流:references/DEPLOYMENT_EXAMPLES.md
- 性能优化模式:references/PERFORMANCE.md
- Enterprise Search 详情和高级模式:references/ENTERPRISE_SEARCH.md
重要提醒
必须遵循以下关键要求:
- 不要写入文件系统 - 使用对象缓存或 VIP 的存储
- 缓存外部请求 - 始终使用 transient 或对象缓存
- 为所有内容添加前缀 - 函数、类、常量
- 预处理查询 - 始终使用
$wpdb->prepare() - 在本地测试 - 使用 WordPres VIP Local Dev Environment
- 监控扫描结果 - 在审查前处理自动检查发现的问题
- 遵循标准 - WordPress VIP Coding Standards(PHPCS)