2026年5月17日
2026年5月17日
WordPressのメモリ制限(memory limit)エラーを解決する方法
はじめに
WordPressでFatal error: Allowed memory size of XXXXXXX bytes exhaustedというエラーが発生した場合、PHPに割り当てられているメモリが不足しています。wp-config.php、php.ini、.htaccessなど複数の方法でメモリ制限を引き上げることができますが、根本的な原因であるメモリを大量消費するプラグインやコードの最適化も並行して行うことが重要です。
症状・原因
- 管理画面や投稿編集ページで白い画面(WSOD)が表示される
Fatal error: Allowed memory size of 67108864 bytes exhaustedエラーが発生する- 画像アップロードや一括処理(複数投稿の更新など)で突然エラーになる
- 特定のプラグインを有効化するとメモリエラーが発生する
- WooCommerceなどの重いプラグインを導入後からエラーが頻発するようになった
解決手順
ステップ1:メモリエラーの特定とデバッグ方法
<?php
/**
* メモリ使用状況の確認と診断
*
* まずはエラーの詳細を把握することが重要
*/
// --- 現在のメモリ設定を確認 ---
function check_memory_settings() {
echo 'PHP memory_limit: ' . ini_get( 'memory_limit' ) . '<br>';
echo 'WP_MEMORY_LIMIT: ' . WP_MEMORY_LIMIT . '<br>';
echo 'WP_MAX_MEMORY_LIMIT: ' . WP_MAX_MEMORY_LIMIT . '<br>';
echo '現在のメモリ使用量: ' . size_format( memory_get_usage( true ) ) . '<br>';
echo 'ピーク時メモリ使用量: ' . size_format( memory_get_peak_usage( true ) ) . '<br>';
}
// 管理画面でのみ確認する場合
if ( is_admin() && current_user_can( 'manage_options' ) && isset( $_GET['check_memory'] ) ) {
add_action( 'admin_notices', function() {
echo '<div class="notice notice-info"><pre>';
check_memory_settings();
echo '</pre></div>';
} );
}
/**
* エラーログでメモリエラーを検出する
* WP_DEBUG と WP_DEBUG_LOG を有効にした後、以下のログを確認:
* /wp-content/debug.log
*
* よく見るメモリエラーのパターン:
* - "Fatal error: Allowed memory size of 67108864 bytes exhausted" → 64MB制限
* - "Fatal error: Allowed memory size of 134217728 bytes exhausted" → 128MB制限
* - "Fatal error: Allowed memory size of 268435456 bytes exhausted" → 256MB制限
*
* バイト数から現在の制限値を計算:
* 67108864 = 64MB (64 * 1024 * 1024)
* 134217728 = 128MB (128 * 1024 * 1024)
* 268435456 = 256MB (256 * 1024 * 1024)
*/
/**
* 現在のメモリ使用量をフッターに表示するデバッグ用コード
* 開発環境でのみ使用(本番環境では削除すること)
*/
function show_memory_usage_in_footer() {
if ( ! WP_DEBUG ) return;
$memory_used = memory_get_usage( true );
$memory_peak = memory_get_peak_usage( true );
$memory_limit = ini_get( 'memory_limit' );
printf(
'<div style="position:fixed;bottom:0;right:0;background:#1d2327;color:#fff;padding:8px 12px;font-size:12px;font-family:monospace;z-index:9999;">
メモリ: %s / %s (ピーク: %s)
</div>',
size_format( $memory_used ),
$memory_limit,
size_format( $memory_peak )
);
}
add_action( 'wp_footer', 'show_memory_usage_in_footer' );
add_action( 'admin_footer', 'show_memory_usage_in_footer' );
?>
ステップ2:wp-config.phpでWP_MEMORY_LIMITを設定
<?php
/**
* wp-config.php でのメモリ制限設定
*
* 設定の優先順位(高い順):
* 1. php.ini の memory_limit
* 2. .htaccess の php_value memory_limit
* 3. wp-config.php の WP_MEMORY_LIMIT
*
* WP_MEMORY_LIMIT はWordPress内部でのみ有効で、
* PHP本体の制限を超えることはできない
*/
// --- 通常のフロントエンド処理用メモリ制限 ---
define( 'WP_MEMORY_LIMIT', '256M' );
// --- 管理画面・WP-Cron・一括処理用メモリ制限(フロントより多く設定) ---
define( 'WP_MAX_MEMORY_LIMIT', '512M' );
/**
* 設定値の目安:
*
* 128M → 小規模サイト(プラグイン少数、シンプルなテーマ)
* 256M → 標準的なサイト(推奨値)
* 512M → WooCommerce・多数プラグイン・大量メディア処理あり
* 1024M → 大規模ECサイト・複雑なマルチサイト
*
* 注意:ホスティングプランで上限が決まっていることが多い。
* 共有ホスティングでは 128M〜256M が上限であることが多い。
*/
/**
* WP_MEMORY_LIMIT が効いているか確認するスニペット
* functions.php に一時的に追加して確認後削除する
*/
add_action( 'init', function() {
if ( is_admin() && current_user_can( 'manage_options' ) ) {
$php_limit = ini_get( 'memory_limit' );
$wp_limit = WP_MEMORY_LIMIT;
// PHPの制限がWordPressの設定より低い場合は警告
if ( wp_convert_hr_to_bytes( $php_limit ) < wp_convert_hr_to_bytes( $wp_limit ) ) {
add_action( 'admin_notices', function() use ( $php_limit, $wp_limit ) {
echo '<div class="notice notice-warning"><p>';
printf(
'PHPのメモリ制限(%s)がWordPressの設定(%s)より低いため、WP_MEMORY_LIMITが反映されていない可能性があります。',
esc_html( $php_limit ),
esc_html( $wp_limit )
);
echo '</p></div>';
} );
}
}
} );
?>
ステップ3:php.ini / .htaccessでメモリ制限を設定
<?php
/**
* php.ini での設定(サーバーの php.ini を直接編集できる場合)
*
* ファイルの場所:
* - Linux: /etc/php/8.x/apache2/php.ini または /etc/php.ini
* - 場所の確認: phpinfo() の "Loaded Configuration File" を参照
* - WP-CLI: wp cli info でパスを確認
*
* 設定後は Apache/PHP-FPM の再起動が必要:
* sudo systemctl restart apache2
* sudo systemctl restart php8.2-fpm
*/
/*
; php.ini の設定(このファイルに直接記述)
memory_limit = 256M
max_execution_time = 300
upload_max_filesize = 64M
post_max_size = 64M
*/
/**
* .htaccess での設定(共有ホスティングで php.ini を編集できない場合)
* WordPressルートの .htaccess に追加する
*/
/*
# .htaccess に追加するメモリ設定
# BEGIN Memory Settings
php_value memory_limit 256M
php_value max_execution_time 300
php_value upload_max_filesize 64M
php_value post_max_size 64M
# END Memory Settings
*/
/**
* .user.ini での設定(CGI/FastCGI/PHP-FPM 環境向け)
* WordPress のルートディレクトリに .user.ini ファイルを作成
*/
/*
; .user.ini の内容
memory_limit = 256M
max_execution_time = 300
upload_max_filesize = 64M
post_max_size = 64M
*/
/**
* PHPコードで直接設定する方法(最終手段・制限あり)
* wp-config.php の DB 接続情報より前に記述
* ※ ホスティングの設定によっては効果がない場合がある
*/
@ini_set( 'memory_limit', '256M' );
/**
* 現在の有効なメモリ制限を確認するショートコード(一時的なデバッグ用)
*/
function memory_debug_shortcode() {
if ( ! current_user_can( 'manage_options' ) ) return '';
return sprintf(
'<pre>PHP memory_limit: %s
WP_MEMORY_LIMIT: %s
現在使用量: %s
ピーク使用量: %s</pre>',
ini_get( 'memory_limit' ),
WP_MEMORY_LIMIT,
size_format( memory_get_usage( true ) ),
size_format( memory_get_peak_usage( true ) )
);
}
add_shortcode( 'memory_debug', 'memory_debug_shortcode' );
?>
ステップ4:Query Monitorでメモリを消費するプラグインを特定
<?php
/**
* Query Monitor プラグインによるメモリプロファイリング
*
* Query Monitor は無料のWordPressデバッグプラグインで、
* 各リクエストのメモリ使用量・クエリ数・処理時間を可視化できる
* https://ja.wordpress.org/plugins/query-monitor/
*
* 使い方:
* 1. Query Monitorをインストール・有効化
* 2. 管理画面下部のデバッグバーでメモリ使用量を確認
* 3. 「Hooks & Actions」タブでどのフックでメモリが増加するか確認
*/
/**
* プラグインごとのメモリ消費量を測定するカスタムコード
* mu-plugins に追加して各プラグインのメモリ影響を測定
*/
class Plugin_Memory_Profiler {
private static $before_memory = array();
private static $plugin_memory = array();
public static function init() {
// 各プラグイン読み込み前後でメモリを記録
add_action( 'plugin_loaded', array( __CLASS__, 'record_after_load' ), PHP_INT_MAX );
}
public static function record_after_load( $plugin_file ) {
$plugin_name = basename( dirname( $plugin_file ) );
if ( '.' === $plugin_name ) {
$plugin_name = basename( $plugin_file, '.php' );
}
self::$plugin_memory[ $plugin_name ] = memory_get_usage( true );
}
public static function output_report() {
if ( ! current_user_can( 'manage_options' ) ) return;
if ( ! isset( $_GET['memory_report'] ) ) return;
echo '<pre style="background:#1d2327;color:#cdd6f4;padding:20px;margin:20px;">';
echo "=== プラグインメモリ使用量レポート ===\n\n";
$prev_memory = 0;
foreach ( self::$plugin_memory as $plugin => $memory ) {
$diff = $memory - $prev_memory;
printf(
"%-40s %10s (+%s)\n",
$plugin,
size_format( $memory ),
size_format( max( 0, $diff ) )
);
$prev_memory = $memory;
}
echo "\n合計: " . size_format( memory_get_usage( true ) );
echo '</pre>';
}
}
// mu-plugins での使用例
// Plugin_Memory_Profiler::init();
// add_action( 'admin_footer', array( 'Plugin_Memory_Profiler', 'output_report' ) );
/**
* 特定のフックでメモリ使用量を記録するシンプルな方法
*/
function log_memory_at_hook( $hook_name ) {
add_action( $hook_name, function() use ( $hook_name ) {
error_log( sprintf(
'[Memory] %s: %s (peak: %s)',
$hook_name,
size_format( memory_get_usage( true ) ),
size_format( memory_get_peak_usage( true ) )
) );
}, PHP_INT_MAX );
}
// 主要なフックでメモリを記録(開発時のみ使用)
if ( WP_DEBUG ) {
log_memory_at_hook( 'plugins_loaded' );
log_memory_at_hook( 'after_setup_theme' );
log_memory_at_hook( 'init' );
log_memory_at_hook( 'wp' );
}
?>
ステップ5:メモリ効率を改善するコードレベルの最適化
<?php
/**
* PHPコードのメモリ使用量を削減するベストプラクティス
*/
// =======================================================
// NG例:大量のオブジェクトをメモリに保持
// =======================================================
function bad_get_all_posts() {
// 全投稿をWP_Postオブジェクトの配列として取得(メモリを大量消費)
$all_posts = get_posts( array(
'numberposts' => -1, // 全件取得は危険
'post_status' => 'any', // 全ステータスを対象
) );
foreach ( $all_posts as $post ) {
// 処理...
}
return $all_posts; // 大量のオブジェクトをメモリに保持したまま返す
}
// =======================================================
// OK例:必要な情報のみ取得してメモリを節約
// =======================================================
function good_get_post_data() {
global $wpdb;
// 必要なフィールドのみを直接SQLで取得(WP_Postオブジェクトを作らない)
$post_data = $wpdb->get_results(
"SELECT ID, post_title, post_date
FROM {$wpdb->posts}
WHERE post_status = 'publish'
AND post_type = 'post'
ORDER BY post_date DESC
LIMIT 100", // 必要な件数のみ
ARRAY_A // 連想配列で返す(オブジェクトより軽量)
);
return $post_data;
}
// =======================================================
// WP_Queryでのメモリ最適化オプション
// =======================================================
function optimized_wp_query_example() {
$query = new WP_Query( array(
'post_type' => 'post',
'posts_per_page' => 50,
'no_found_rows' => true, // ページネーション不要時に使用(COUNTクエリを省略)
'update_post_meta_cache' => false, // メタキャッシュを無効(メタ不要の場合)
'update_post_term_cache' => false, // タームキャッシュを無効(タクソノミー不要の場合)
'fields' => 'ids', // IDのみ取得(WP_Postオブジェクトを生成しない)
) );
// IDのみで処理する場合
$post_ids = $query->posts; // array(1, 2, 3, ...)
// 必要な投稿を個別に取得
foreach ( $post_ids as $post_id ) {
$title = get_the_title( $post_id );
// 処理...
// 使い終わったデータをメモリから解放
clean_post_cache( $post_id );
}
wp_reset_postdata();
}
// =======================================================
// 大量データ処理時のバッチ処理
// =======================================================
function process_posts_in_batches( $total_posts, $batch_size = 100 ) {
$offset = 0;
$processed = 0;
while ( $offset < $total_posts ) {
// バッチサイズ分ずつ処理
$posts = get_posts( array(
'numberposts' => $batch_size,
'offset' => $offset,
'post_status' => 'publish',
'fields' => 'ids',
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
) );
if ( empty( $posts ) ) break;
foreach ( $posts as $post_id ) {
// 各投稿を処理...
$processed++;
// 処理後にキャッシュをクリアしてメモリを解放
clean_post_cache( $post_id );
}
$offset += $batch_size;
// PHPのガベージコレクタを明示的に呼ぶ(長時間処理の場合)
if ( function_exists( 'gc_collect_cycles' ) ) {
gc_collect_cycles();
}
}
return $processed;
}
// =======================================================
// 不要な処理を外す(使わないフックを削除)
// =======================================================
function optimize_wp_hooks() {
// フロントエンドでoEmbedが不要な場合は削除
remove_action( 'wp_head', 'wp_oembed_add_discovery_links' );
// RSSフィードが不要な場合は削除
remove_action( 'wp_head', 'feed_links', 2 );
remove_action( 'wp_head', 'feed_links_extra', 3 );
// 絵文字スクリプトを削除(使わない場合)
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
remove_action( 'wp_print_styles', 'print_emoji_styles' );
remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
remove_action( 'admin_print_styles', 'print_emoji_styles' );
}
add_action( 'init', 'optimize_wp_hooks' );
?>
注意事項
- ホスティングの上限:
WP_MEMORY_LIMITはPHPのmemory_limitの上限を超えて設定しても無効です。共有ホスティングではサポートに問い合わせて上限を確認してください - 制限を上げるだけでは不十分: メモリを増やすことは一時的な解決策です。根本原因(メモリリークのあるプラグイン、非効率なクエリなど)を特定して修正することが重要です
no_found_rowsの注意点: ページネーションに必要なmax_num_pagesが取得できなくなるため、ページネーションのある一覧ページではfalseのままにしてください- 定期的なガベージコレクション: 長時間のバッチ処理では
gc_collect_cycles()を適切な間隔で呼び出してメモリを解放してください
まとめ
WordPressのメモリエラーはWP_MEMORY_LIMIT/WP_MAX_MEMORY_LIMIT定数、php.ini、.htaccessの3段階で対応し、Query Monitorでメモリを消費するプラグインを特定、no_found_rowsやfields => idsなどのクエリ最適化で根本的な改善を行うことが重要です。関連記事:WordPressのwp-config.phpを正しく設定してセキュリティを強化する方法