はじめてのWordPressプラグイン開発 - 作成編

WordPressプラグイン開発に興味はあるけれど、どこから始めれば良いかわからない...そんな方に向けて、実際に開発・公開した「Category Color Picker」プラグインを例に、プラグイン開発の基本から実践までを解説します。

## 対象読者

- WordPressの基本構造をなんとなく理解している方
- HTML、JavaScript、PHPの基礎知識がなんとなくある方  
- WordPressプラグイン開発になんとなく興味がある方

## 開発環境

- **WordPress**: 6.4以降
- **PHP**: 7.4以降
- **開発環境**: ローカル環境（XAMPP、Local by Flywheel等）

## 今回作成するプラグインの概要

**Category Color Picker**は、WordPressのカテゴリーに色を設定し、その色をフロントエンドの投稿一覧などに反映できるプラグインです。

### 主な機能

1. **カテゴリー編集画面にカラーピッカーを追加**
2. **カテゴリー一覧に色列を表示**
3. **設定可能なCSSセレクタでカテゴリー色を反映**
4. **相対輝度に基づく自動テキスト色調整**

## プラグイン開発の基本構造

### 1. プラグインの雛形作成

まず、プラグインの基本的なファイル構成を作成します。

```
category-color-picker/
├── category-color-picker.php (メインファイル)
├── category-color-picker.js (JavaScript)
├── readme.txt (プラグイン説明)
└── languages/ (日本語対応)
    ├── category-color-picker.pot
    ├── category-color-picker-ja.po
    └── category-color-picker-ja.mo
```

### 2. プラグインヘッダーの作成

`category-color-picker.php`の冒頭に、WordPressがプラグインとして認識するためのヘッダーコメントを記述します。

```php
<?php
/**
 * Plugin Name: Category Color Picker
 * Description: Add a color picker to categories and reflect category colors in post listings and other selectors.
 * Version: 1.0.0
 * Author: あなたの名前
 * Text Domain: category-color-picker
 * Requires at least: 5.0
 * Requires PHP: 7.4
 * License: GPL v2 or later
 */

// 直接アクセスを防ぐ
if (!defined('ABSPATH')) {
    exit;
}
```

### 3. プラグインクラスの基本構造

```php
class CategoryColorPicker {
    
    public function __construct() {
        add_action('init', array($this, 'init'));
    }
    
    public function init() {
        // 管理画面でのみ動作
        if (is_admin() && is_user_logged_in()) {
            $this->init_admin();
        }
        
        // フロントエンドでの動作
        if (!is_admin()) {
            $this->init_frontend();
        }
    }
    
    private function init_admin() {
        // カテゴリー編集フックを追加
        add_action('category_add_form_fields', array($this, 'add_category_color_field'));
        add_action('category_edit_form_fields', array($this, 'edit_category_color_field'));
        
        // カテゴリー保存処理
        add_action('created_category', array($this, 'save_category_color'));
        add_action('edited_category', array($this, 'save_category_color'));
        
        // 管理画面のメニュー追加
        add_action('admin_menu', array($this, 'add_admin_menu'));
        
        // スクリプトとスタイルの読み込み
        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
    }
    
    private function init_frontend() {
        // フロントエンドでCSSを出力
        add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_styles'));
    }
}

// プラグインを初期化
new CategoryColorPicker();
```

## 機能実装のポイント

### 1. カラーピッカーの追加

WordPressの標準カラーピッカーを使用して、カテゴリー編集画面にカラーピッカーを追加します。

```php
public function add_category_color_field() {
    ?>
    <div class="form-field">
        <label for="category_color"><?php esc_html_e('Category Color', 'category-color-picker'); ?></label>
        <input type="text" name="category_color" id="category_color" class="color-picker" value="#000000" />
        <p class="description"><?php esc_html_e('Select the color to use for this category.', 'category-color-picker'); ?></p>
    </div>
    <?php
}

public function edit_category_color_field($term) {
    $color = get_term_meta($term->term_id, 'category_color', true);
    if (empty($color)) {
        $color = '#000000';
    }
    ?>
    <tr class="form-field">
        <th scope="row" valign="top">
            <label for="category_color"><?php esc_html_e('Category Color', 'category-color-picker'); ?></label>
        </th>
        <td>
            <input type="text" name="category_color" id="category_color" class="color-picker" value="<?php echo esc_attr($color); ?>" />
            <p class="description"><?php esc_html_e('Select the color to use for this category.', 'category-color-picker'); ?></p>
        </td>
    </tr>
    <?php
}
```

### 2. データの保存処理

カテゴリーメタデータとしてカラー情報を保存します。セキュリティ対策として、適切なNonce検証とサニタイズを行います。

```php
public function save_category_color($term_id) {
    // Nonce検証
    if (isset($_POST['tag-name'])) {
        // 新規カテゴリー作成時
        if (!isset($_POST['_wpnonce_add-tag']) || !wp_verify_nonce(wp_unslash($_POST['_wpnonce_add-tag']), 'add-tag')) {
            return;
        }
    } else {
        // カテゴリー編集時
        if (!isset($_POST['_wpnonce']) || !wp_verify_nonce(wp_unslash($_POST['_wpnonce']), 'update-tag_' . $term_id)) {
            return;
        }
    }
    
    // 権限チェック
    if (!current_user_can('manage_categories')) {
        return;
    }
    
    // カラー値の処理
    if (isset($_POST['category_color'])) {
        $color = sanitize_hex_color(wp_unslash($_POST['category_color']));
        if ($color) {
            update_term_meta($term_id, 'category_color', $color);
        } else {
            delete_term_meta($term_id, 'category_color');
        }
    }
}
```

### 3. JavaScriptでカラーピッカーを有効化

```javascript
jQuery(document).ready(function($) {
    // WordPress標準のカラーピッカーを初期化
    $('.color-picker').wpColorPicker();
});
```

### 4. フロントエンドでのCSS出力

設定されたカテゴリーカラーをCSSとして出力し、フロントエンドに反映します。

```php
public function output_category_colors_css() {
    $categories = get_categories(array('hide_empty' => false));
    
    if (empty($categories)) {
        return;
    }
    
    $selectors = get_option('category_color_selectors', $this->get_default_selectors());
    $css_rules = array();
    
    foreach ($categories as $category) {
        $color = get_term_meta($category->term_id, 'category_color', true);
        if (!$color) {
            continue;
        }
        
        $slug = $category->slug;
        $selectors_for_category = str_replace('{$slug}', $slug, $selectors);
        $text_color = $this->get_contrast_color($color);
        
        $css_rules[] = $selectors_for_category . ' {';
        $css_rules[] = '    background: ' . esc_attr($color) . ' !important;';
        $css_rules[] = '    color: ' . $text_color . ' !important;';
        $css_rules[] = '}';
    }
    
    if (!empty($css_rules)) {
        wp_add_inline_style('category-color-picker-frontend', implode("\n", $css_rules));
    }
}

private function get_contrast_color($hex_color) {
    // 16進カラーコードをRGBに変換
    $hex_color = ltrim($hex_color, '#');
    $r = hexdec(substr($hex_color, 0, 2));
    $g = hexdec(substr($hex_color, 2, 2));
    $b = hexdec(substr($hex_color, 4, 2));
    
    // 相対輝度を計算
    $luminance = (0.299 * $r + 0.587 * $g + 0.114 * $b) / 255;
    
    // 明度に基づいてテキスト色を決定
    return $luminance > 0.5 ? 'var(--c-text, hsl(223, 6%, 13%))' : '#FFF';
}
```

## セキュリティ対策

WordPressプラグインでは、セキュリティ対策が重要です。

### 1. データのエスケープ

```php
// 出力時のエスケープ
echo esc_html($category_name);
echo esc_attr($color_value);
echo esc_url($link_url);
```

### 2. 入力データのサニタイズ

```php
// 入力データのサニタイズ
$color = sanitize_hex_color(wp_unslash($_POST['category_color']));
$text = sanitize_text_field(wp_unslash($_POST['text_field']));
```

### 3. Nonce検証

```php
// フォームにNonceを追加
wp_nonce_field('category_color_action', 'category_color_nonce');

// 検証
if (!wp_verify_nonce($_POST['category_color_nonce'], 'category_color_action')) {
    wp_die('Security check failed');
}
```

## 日本語化対応

日本語対応のため、テキストドメインを使用します。

```php
// テキストの日本語化
esc_html_e('Category Color', 'category-color-picker');
$message = esc_html__('Settings saved.', 'category-color-picker');
```

言語ファイルの作成：

```
# languages/category-color-picker.pot (テンプレート)
msgid "Category Color"
msgstr ""

msgid "Settings saved."
msgstr ""
```

```
# languages/category-color-picker-ja.po (日本語翻訳)
msgid "Category Color"
msgstr "カテゴリーカラー"

msgid "Settings saved."
msgstr "設定が保存されました。"
```

## デバッグとテスト

### 1. WordPressデバッグモードの有効化

`wp-config.php`でデバッグモードを有効にします：

```php
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
```

### 2. プラグインチェックツールの使用

WordPress.orgの[Plugin Check](https://wordpress.org/plugins/plugin-check/)プラグインを使用して、コード品質をチェックします。

### 3. 異なる環境でのテスト

- 異なるWordPressバージョン
- 異なるテーマ
- 他のプラグインとの互換性

## まとめ

この記事では、「Category Color Picker」プラグインを例に、WordPressプラグイン開発の基本的な流れを解説しました。

### 学んだポイント

- **プラグインの基本構造とファイル配置**
- **WordPressフックとアクションの使い方**
- **セキュリティ対策の重要性**
- **日本語化対応の方法**
- **デバッグとテストの手法**

### 次のステップ

プラグインが完成したら、次は「申請・登録編」でWordPress.org公式ディレクトリへの掲載方法を学びましょう。

開発したプラグインを世界中のWordPressユーザーに使ってもらえるよう、しっかりとした品質とセキュリティを確保することが重要です。プラグイン開発は最初は難しく感じるかもしれませんが、一歩ずつ学んでいけば、プラグインを作ることができます。