0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

php初心者のなのたんがWordpressプラグインをChatGPTで1時間ちょいで作るの巻き

Last updated at Posted at 2025-02-27

はじめに

やりたいことはこれ

nginx + fpmの環境で無料でwebp、AVIFに圧縮できない

このサイトで使うものなのね

ないものは作ってしまおうなの、ってことで
ChatGPT というWindowsアプリを起動

確かにWordpressテーマは作ったものの、プラグインははじめて

最初のステップ

Wordpressのプラグインの作り方

  1. プラグインのフォルダとファイルを作成
    まず、wp-content/plugins/ ディレクトリに移動し、新しいフォルダを作ります。例えば my-custom-plugin というフォルダを作成。
    その中に my-custom-plugin.php というファイルを作成します。
<?php
/**
 * Plugin Name: My Custom Plugin
 * Plugin URI:  https://example.com/
 * Description: シンプルなカスタムプラグイン
 * Version:     1.0
 * Author:      あなたの名前
 * Author URI:  https://example.com/
 * License:     GPL2
 *```
  1. 基本的なフックを追加
    WordPressの動作をカスタマイズするためにフック(Hook)を使います。

(1) メニューに設定ページを追加
管理画面のメニューに新しい項目を追加するには add_menu_page() を使います。

function my_plugin_menu() {
    add_menu_page(
        'My Plugin Settings',   // ページタイトル
        'My Plugin',            // メニュータイトル
        'manage_options',       // 権限
        'my-plugin',            // メニューのスラッグ
        'my_plugin_settings'    // 表示する関数
    );
}

function my_plugin_settings() {
    echo '<h1>My Plugin Settings</h1>';
    echo '<p>ここに設定を追加できます。</p>';
}

add_action('admin_menu', 'my_plugin_menu');

他にもショートコードとかajaxとか紹介してくれるのですが、今回使わない

最後に

どんなプラグインを作りたいですか? 具体的な機能が決まっていれば、それに合わせたコードを用意できますよ!

というわけで、言ってみました

まずコードを出させる

nginx+fpmの環境でWordpressを使用時、mod_rewriteが使えない環境での
webp画像変換
キャッシュ系プラグインをOFFにした前提で
Accpect webpヘッダを確認して、自サーバー分の画像の自動的に出力したHTMLをfilename.jpg.webpとかにして
出力したい、もしくは
JavaScriptを用いてリライトをしたい
リライトがなくなることでApacheでもリライト分の遅延がなくなると思う

そうしたらこうなりました

Nginx + PHP-FPM 環境で mod_rewrite を使わずに WebP 画像を配信する方法

Apache の mod_rewrite を使わずに WebP 画像を配信する方法には、大きく分けて以下の2つのアプローチがあります。

Nginx で Accept ヘッダーをチェックし、WebP を直接配信する
JavaScript を使い、クライアント側で WebP 画像を差し替える
キャッシュ系プラグインが無効になっている前提で、どちらの方法でも WebP 画像を優先的に配信できます。

方法 1: Nginx で WebP 画像を配信
無視

方法 2: JavaScript を使って WebP に置き換える
候補

というわけで

どちらの方法で進めたいですか?また、WebP 画像の生成も自動化したいですか?

nginx.confとかの設定をなしに何もかも自動化したい

その答えはこれでした

① プラグインで画像アップロード時に WebP を自動生成

function generate_webp_on_upload($metadata) {
    $upload_dir = wp_upload_dir();
    $base_dir = $upload_dir['basedir'];

    foreach ($metadata['sizes'] as $size) {
        $file_path = $base_dir . '/' . $size['file'];
        $webp_path = $file_path . '.webp';

        if (!file_exists($webp_path) && function_exists('imagewebp')) {
            $image = imagecreatefromstring(file_get_contents($file_path));
            if ($image) {
                imagewebp($image, $webp_path, 80); // 80は圧縮率(0~100)
                imagedestroy($image);
            }
        }
    }
    return $metadata;
}
add_filter('wp_generate_attachment_metadata', 'generate_webp_on_upload');

② 出力する HTML の を自動で WebP に置換

function replace_images_with_webp($content) {
    if (strpos($_SERVER['HTTP_ACCEPT'], 'image/webp') !== false) {
        $content = preg_replace('/\.(jpg|jpeg|png)/i', '.${1}.webp', $content);
    }
    return $content;
}
add_filter('the_content', 'replace_images_with_webp');

③ JavaScript で WebP に置き換える

document.addEventListener("DOMContentLoaded", function () {
    if (!document.createElement("canvas").toDataURL("image/webp").startsWith("data:image/webp")) {
        return;
    }

    document.querySelectorAll("img").forEach((img) => {
        if (img.src.match(/\.(jpg|jpeg|png)$/)) {
            let webpSrc = img.src + ".webp";

            let xhr = new XMLHttpRequest();
            xhr.open("HEAD", webpSrc, true);
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4 && xhr.status === 200) {
                    img.src = webpSrc;
                }
            };
            xhr.send();
        }
    });
});

このもとから

webp-converter.php
<?php
/**
 * Plugin Name: WebP Converter
 * Description: 自動で WebP を作成し、HTML を変換する
 * Version: 1.0
 * Author: あなたの名前
 */

function generate_webp_on_upload($metadata) {
    $upload_dir = wp_upload_dir();
    $base_dir = $upload_dir['basedir'];

    foreach ($metadata['sizes'] as $size) {
        $file_path = $base_dir . '/' . $size['file'];
        $webp_path = $file_path . '.webp';

        if (!file_exists($webp_path) && function_exists('imagewebp')) {
            $image = imagecreatefromstring(file_get_contents($file_path));
            if ($image) {
                imagewebp($image, $webp_path, 80);
                imagedestroy($image);
            }
        }
    }
    return $metadata;
}
add_filter('wp_generate_attachment_metadata', 'generate_webp_on_upload');

function replace_images_with_webp($content) {
    if (strpos($_SERVER['HTTP_ACCEPT'], 'image/webp') !== false) {
        $content = preg_replace('/\.(jpg|jpeg|png)/i', '.${1}.webp', $content);
    }
    return $content;
}
add_filter('the_content', 'replace_images_with_webp');

function webp_converter_enqueue_script() {
    wp_enqueue_script('webp-converter', plugin_dir_url(__FILE__) . 'webp-converter.js', array(), null, true);
}
add_action('wp_enqueue_scripts', 'webp_converter_enqueue_script');
webp-converter.js
document.addEventListener("DOMContentLoaded", function () {
    if (!document.createElement("canvas").toDataURL("image/webp").startsWith("data:image/webp")) {
        return;
    }

    document.querySelectorAll("img").forEach((img) => {
        if (img.src.match(/\.(jpg|jpeg|png)$/)) {
            let webpSrc = img.src + ".webp";

            let xhr = new XMLHttpRequest();
            xhr.open("HEAD", webpSrc, true);
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4 && xhr.status === 200) {
                    img.src = webpSrc;
                }
            };
            xhr.send();
        }
    });
});

ができました

欲がだんだん出てくる

プラグイン設定画面を作る(画質調整や書き換えの ON/OFF を設定可能にする)
既存の画像も WebP に変換する機能を追加(バッチ処理)

のコードは?

とかしていくがどんどん出力してくれます

buggy-autoconvert.php
// 一括変換のボタンを追加
function webp_converter_add_bulk_convert_button() {
    ?>
    <form method="post" action="">
        <input type="hidden" name="webp_bulk_convert" value="1">
        <?php submit_button('既存画像を WebP に変換'); ?>
    </form>
    <?php
    if (isset($_POST['webp_bulk_convert'])) {
        webp_convert_existing_images();
    }
}
add_action('admin_notices', 'webp_converter_add_bulk_convert_button');

// 既存画像を WebP に変換
function webp_convert_existing_images() {
    $upload_dir = wp_upload_dir();
    $base_dir = $upload_dir['basedir'];
    $files = glob($base_dir . '/**/*.{jpg,jpeg,png}', GLOB_BRACE);

    if (!$files) {
        echo '<div class="notice notice-error"><p>変換する画像が見つかりません。</p></div>';
        return;
    }

    $quality = get_option('webp_quality', 80);
    $converted_count = 0;

    foreach ($files as $file) {
        $webp_path = $file . '.webp';

        if (!file_exists($webp_path) && function_exists('imagewebp')) {
            $image = imagecreatefromstring(file_get_contents($file));
            if ($image) {
                imagewebp($image, $webp_path, $quality);
                imagedestroy($image);
                $converted_count++;
            }
        }
    }

    echo '<div class="notice notice-success"><p>' . $converted_count . ' 件の画像を WebP に変換しました。</p></div>';
}

これが動かなかったのです

既存画像をWebpに変換ボタンを押したら、変換する画像が見つかりません、と出た

として

✅ 1. glob() のパスが間違っている
現在のコードでは glob() を使って wp-content/uploads/ 以下の画像を探しています。
しかし、以下の問題で画像が見つからないことがあります。

wp_upload_dir() の basedir が 正しく取得できていない
glob() の 検索パターンが間違っている
画像の拡張子が .JPG など 大文字 で保存されている
🔹 修正コード(glob() の検索パスを修正)

function webp_convert_existing_images() {
    $upload_dir = wp_upload_dir();
    $base_dir = $upload_dir['basedir']; // 例: /home/username/public_html/wp-content/uploads
    $quality = get_option('webp_quality', 80);

    // 再帰的に検索し、すべての jpg/jpeg/png を取得(大文字・小文字対応)
    $files = glob($base_dir . '/**/*.{jpg,jpeg,png,JPG,JPEG,PNG}', GLOB_BRACE);

    if (!$files) {
        echo '<div class="notice notice-error"><p>変換する画像が見つかりません。フォルダや拡張子を確認してください。</p></div>';
        return;
    }

    $converted_count = 0;

    foreach ($files as $file) {
        $webp_path = $file . '.webp';

        if (!file_exists($webp_path) && function_exists('imagewebp')) {
            $image = imagecreatefromstring(file_get_contents($file));
            if ($image) {
                imagewebp($image, $webp_path, $quality);
                imagedestroy($image);
                $converted_count++;
            }
        }
    }

    echo '<div class="notice notice-success"><p>' . $converted_count . ' 件の画像を WebP に変換しました。</p></div>';
}

で、治ったのです

たまにバグ出すコードを出すのでプチ怒りするのですが
何かといってできた一番最初のコードはこれになるの

ここまで1時間強
このコードはちゃんと動きました

もっと欲をつけて、まぁまぁ出来上がり

image.png

割と使えるツールになってきました
ただ、avif変換の枚数が多いと504になるものの

Wordpressプラグインディレクトリに掲載されるのを目標に
まったりと行こうかと思います

また作ってしまった

記事を何分で読めるか?というプラグインがあるけど
なにかといってめんどくさいの

というわけでまたChatGPTにお願いしたの

Wordpressのプラグインを作ってほしいの
記事ページすべての先頭に
「この記事は何分何秒で読めます」
と表示させたい
300文字で1分とカウントしたい

無意味に秒までカウントさせるの

しかし、初版は明らかにHTMLの中身までカウントしていたので
修正させたのが、以下です

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?