mcpField
W
wordpress-vip

wordpress-vip

github.com/trewknowledge开发235 次安装17 周前更新
代码仓库

关于 wordpress-vip

面向 WordPress VIP 应用开发者的技能,指导遵守平台的编码要求。重点涵盖安全、性能、部署检查及 VIP 特定实践。

主要功能

  1. 01WordPress VIP 编码限制
  2. 02安全处理输入与输出
  3. 03优化并限制数据库查询
  4. 04缓存外部请求
  5. 05部署与审查清单

适用场景

  1. 01检查代码是否符合 VIP 平台限制
  2. 02准备 WordPress VIP 变更并部署
  3. 03优化查询与外部 API 调用

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/trewknowledge/agent-skills --skill wordpress-vip

安装后在 Claude Code 中输入/wordpress-vip确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
DEPLOYMENT_EXAMPLES.md
ENTERPRISE_SEARCH.md
PERFORMANCE.md
VIP_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 会监控代码仓库并自动部署更改。

  1. 开发:推送到 develop 分支 → 部署到 develop 环境
  2. 暂存:推送到 master/main 分支 → 部署到暂存环境
  3. 生产:通过 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 的要求。

其他资源

你可以在以下参考文档中找到更详细的信息:

重要提醒

必须遵循以下关键要求:

  1. 不要写入文件系统 - 使用对象缓存或 VIP 的存储
  2. 缓存外部请求 - 始终使用 transient 或对象缓存
  3. 为所有内容添加前缀 - 函数、类、常量
  4. 预处理查询 - 始终使用 $wpdb->prepare()
  5. 在本地测试 - 使用 WordPres VIP Local Dev Environment
  6. 监控扫描结果 - 在审查前处理自动检查发现的问题
  7. 遵循标准 - WordPress VIP Coding Standards(PHPCS)

评论

支持 Markdown