mcpField
W
wordpress-vip

wordpress-vip

github.com/trewknowledge開発235 回インストール17 週間前に更新
リポジトリ

wordpress-vip について

WordPress VIP アプリケーションの開発者向けスキルです。プラットフォーム固有の規則に沿ったセキュリティ、パフォーマンス、デプロイ前の確認を扱います。

主な機能

  1. 01WordPress VIP のコーディング制約
  2. 02入力と出力の安全な処理
  3. 03データベースクエリの最適化と制限
  4. 04外部リクエストのキャッシュ
  5. 05デプロイとレビューのチェックリスト

活用シーン

  1. 01VIP のプラットフォーム制約に沿ったコード確認
  2. 02WordPress 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 Local Dev Environment または 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 Local Dev Environment を使用してください。

WordPress VIP Local Dev Environment のセットアップ:

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 Local Development documentation をご覧ください。

デプロイのワークフロー

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
デプロイ前チェックリスト

デプロイ前に、次の項目を確認してください。

  • コードが WordPress VIP ルールセットで PHPCS に合格する
  • 制限対象の関数を使用していない
  • すべての外部リクエストがキャッシュされている
  • データベースクエリが最適化されている
  • ユーザー入力がサニタイズされている
  • 出力がエスケープされている
  • ファイルシステムへの書き込みがない
  • ローカルの 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 は wp_schedule_event の代わりに、(WordPress VIP MU プラグインに含まれている)Cron Control の使用を強く推奨しています。生の 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. 外部リクエストをキャッシュする - 常にトランジェントまたは オブジェクトキャッシュ を使用する
  3. すべてにプレフィックスを付ける - 関数、クラス、定数
  4. クエリをプリペアする - 常に $wpdb->prepare() を使用する
  5. ローカルでテストする - WordPres VIP Local Dev Environment を使用する
  6. スキャン結果を監視する - レビュー前に自動スキャンで検出された問題に対処する
  7. 標準に従う - WordPress VIP Coding Standards(PHPCS)

コメント