はじめに
やりたいことはこれ
nginx + fpmの環境で無料でwebp、AVIFに圧縮できない
このサイトで使うものなのね
ないものは作ってしまおうなの、ってことで
ChatGPT というWindowsアプリを起動
確かにWordpressテーマは作ったものの、プラグインははじめて
最初のステップ
Wordpressのプラグインの作り方
- プラグインのフォルダとファイルを作成
まず、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
*```
- 基本的なフックを追加
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');
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();
}
});
});
このもとから
<?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');
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 に変換する機能を追加(バッチ処理)
のコードは?
とかしていくがどんどん出力してくれます
// 一括変換のボタンを追加
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時間強
このコードはちゃんと動きました
もっと欲をつけて、まぁまぁ出来上がり
割と使えるツールになってきました
ただ、avif変換の枚数が多いと504になるものの
Wordpressプラグインディレクトリに掲載されるのを目標に
まったりと行こうかと思います
また作ってしまった
記事を何分で読めるか?というプラグインがあるけど
なにかといってめんどくさいの
というわけでまたChatGPTにお願いしたの
Wordpressのプラグインを作ってほしいの
記事ページすべての先頭に
「この記事は何分何秒で読めます」
と表示させたい
300文字で1分とカウントしたい
無意味に秒までカウントさせるの
しかし、初版は明らかにHTMLの中身までカウントしていたので
修正させたのが、以下です