WordPress フック一覧
開発者が実際に使う WordPress のアクションとフィルターを検索できる一覧。正確な add_action / add_filter のシグネチャ、発火するタイミング、動作するサンプル、そして人がハマりがちなポイントを掲載しています。
63 個のフックを、正確な add_action / add_filter のシグネチャ、発火するタイミング、動作するサンプル、そしてつまずきやすいポイントとともに収録しています。 4 個は「未検証」としてマークされています。引数の数を WordPress のソースと照合していないため、推測を事実として提示するよりも、その旨を明示することにしています。
これは網羅的なものではありませんし、そのつもりもありません。WordPress には数千ものフックがあります。ここで扱うのは、実際によく使われるものだけです。
WordPress の読み込みが完了した後、ヘッダーが送信される前に実行されます。カスタム投稿タイプ、タクソノミー、リライトルールを登録する標準的な場所です。
発火タイミング
フロントエンドと管理画面の両方で、すべてのリクエストにおいて、コア・プラグイン・テーマの読み込み後に発火します。
シグネチャ
add_action( 'init', 'my_callback' );サンプル
add_action( 'init', function () {
register_post_type( 'book', array(
'public' => true,
'label' => 'Books',
'show_in_rest' => true, // required for the block editor
) );
} );落とし穴
init は AJAX、REST、cron を含むすべてのリクエストで実行されます。ここで時間のかかる処理(HTTP リクエストや重いクエリ)を行うと、ページ読み込みのすべてに負荷がかかります。また、ここでは現在のユーザーを取得できますが、まだ何も出力できません。ヘッダーはまだ送信されていないものの、まさに送信されようとしているためです。
テーマが読み込まれた時点で実行されます。add_theme_support()、add_image_size()、ナビゲーションメニューの登録を行う正しい場所です。
発火タイミング
テーマの functions.php が読み込まれた後、init より前に発火します。
シグネチャ
add_action( 'after_setup_theme', 'my_callback' );サンプル
add_action( 'after_setup_theme', function () {
add_theme_support( 'post-thumbnails' );
add_theme_support( 'title-tag' );
add_image_size( 'card', 600, 400, true ); // true = hard crop
} );落とし穴
ここではなく init で画像サイズを登録すると、たいていの場合はたまたま動いてしまい、一部のケースで原因不明の不具合を起こします。after_setup_theme を使いましょう。まさにそのためのフックです。
有効なプラグインがすべて読み込まれた時点で実行されます。他のプラグインとやり取りできる、最も早い安全なタイミングです。
発火タイミング
すべてのプラグインファイルが読み込まれた後、テーマが読み込まれる前に発火します。
シグネチャ
add_action( 'plugins_loaded', 'my_callback' );落とし穴
ここではまだ現在のユーザーを取得できません。wp_get_current_user() は確実には動作しません。ユーザーが必要な場合は init を使いましょう。
WordPress が完全に読み込まれた後に実行されます。プラグイン、テーマ、init、ユーザーがすべて準備完了した状態です。
発火タイミング
init の後、現在のユーザーが設定された後に発火します。
シグネチャ
add_action( 'wp_loaded', 'my_callback' );すべての管理画面リクエストの冒頭で実行されます。register_setting()、権限チェック、管理画面のリダイレクトに使います。
発火タイミング
管理画面側のすべてのリクエストで発火します。
シグネチャ
add_action( 'admin_init', 'my_callback' );落とし穴
このフックは、本当の意味では「管理画面」ではない admin-ajax.php のリクエストでも発火します。コールバックが画面の存在を前提としている場合は、wp_doing_ajax() でガードしましょう。
フロントエンドの CSS と JavaScript を読み込む(エンキューする)、唯一の正しい場所です。
発火タイミング
フロントエンドのページ読み込み時、head がレンダリングされる前に発火します。
シグネチャ
add_action( 'wp_enqueue_scripts', 'my_callback' );サンプル
add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_style(
'child-style',
get_stylesheet_uri(),
array( 'parent-style' ), // load AFTER the parent
wp_get_theme()->get( 'Version' ) // cache-bust on version change
);
} );落とし穴
名前に反して、このフックはスクリプトだけでなくスタイルも扱います。wp_enqueue_styles というフックは存在せず、それを探して時間を無駄にする人がいます。また、これは管理画面(admin_enqueue_scripts を使う)やブロックエディター(enqueue_block_editor_assets を使う)では発火しません。
管理画面で CSS / JS を読み込みます。現在の画面のフックサフィックスを受け取るため、特定の画面だけでアセットを読み込めます。
発火タイミング
管理画面のページ読み込み時に発火します。
シグネチャ
add_action( 'admin_enqueue_scripts', 'my_callback' ); // receives $hook_suffixサンプル
add_action( 'admin_enqueue_scripts', function ( $hook ) {
if ( 'settings_page_my-plugin' !== $hook ) {
return; // do not load our JS on every admin screen
}
wp_enqueue_script( 'my-admin', plugins_url( 'admin.js', __FILE__ ), array(), '1.0', true );
} );落とし穴
$hook でガードしないことは、プラグインが無関係な管理画面を壊してしまう最も多い原因です。アセットは必要な場所だけで読み込み、それ以外では読み込まないようにしましょう。
ブロックエディター(Gutenberg)にのみアセットを読み込みます。フロントエンドにも、その他の管理画面にも読み込みません。
発火タイミング
ブロックエディターが読み込まれるときに発火します。
シグネチャ
add_action( 'enqueue_block_editor_assets', 'my_callback' );<head> 内に出力を書き出します。メタタグやインラインのクリティカル CSS に使います。
発火タイミング
フロントエンドの <head> 内で発火します。
シグネチャ
add_action( 'wp_head', 'my_callback' );落とし穴
ここでスクリプトやスタイルをエンキューしてはいけません。wp_enqueue_scripts を使えば、WordPress が依存関係や重複排除を処理してくれます。wp_head に <script> タグを直接出力するとそれらがすべて回避されてしまい、多くのサイトが jQuery を3回読み込んでしまう原因になっています。
</body> の直前に出力を書き出します。アナリティクスのスニペットや遅延読み込みのマークアップに適した場所です。
発火タイミング
フロントエンドのページの末尾で発火します。
シグネチャ
add_action( 'wp_footer', 'my_callback' );落とし穴
wp_footer() の呼び出しを忘れたテーマは、管理バーを壊し、フッターにスクリプトをエンキューするあらゆるプラグインを壊し、wordpress.org のテーマレビューでは自動的に不合格となります。
投稿コンテンツが表示される直前にフィルターします。投稿の前後にマークアップを追加する一般的な場所です。
発火タイミング
the_content() が呼び出されるたびに発火します。
シグネチャ
add_filter( 'the_content', 'my_callback' ); // receives $contentサンプル
add_filter( 'the_content', function ( $content ) {
if ( ! is_singular( 'post' ) || ! in_the_loop() || ! is_main_query() ) {
return $content; // <- the guard everyone forgets
}
return $content . '<p class="cta">Enjoyed this? Read more.</p>';
} );落とし穴
これは思っているよりはるかに頻繁に実行されます。ウィジェット内、REST レスポンス内、一部のプラグインの抜粋生成時、そしてアーカイブのループでは投稿ごとに1回ずつ実行されます。is_singular / in_the_loop / is_main_query によるガードがないと、CTA がブログのインデックスに15回も表示され、RSS フィードの中にまで出てしまいます。これは WordPress で最も誤用されているフィルターです。
表示前に投稿タイトルをフィルターします。
発火タイミング
the_title() または get_the_title() が呼び出されるたびに発火します。
シグネチャ
add_filter( 'the_title', 'my_callback', 10, 2 ); // receives $title, $post_id落とし穴
このフックは、管理メニュー、ナビゲーションメニュー、そしてドキュメントの <title> のタイトルに対しても発火します。無条件にフィルターすると、意図しない場所の名前まで変えてしまいます。
自動生成される抜粋に含まれる単語数を設定します。デフォルトは55です。
発火タイミング
WordPress が、手動の抜粋がない投稿の抜粋を生成するときに発火します。
シグネチャ
add_filter( 'excerpt_length', 'my_callback' ); // receives $length (words)サンプル
add_filter( 'excerpt_length', function ( $length ) {
return 25;
}, 999 ); // high priority: many themes set this too, and last one wins落とし穴
手動の抜粋がある投稿には効果がありません。そうした投稿はそのまま使われます。また、多くのテーマがこのフィルターを自前で設定しているため、優先させるには高い優先度の数値が必要になることがよくあります。
短縮された抜粋の末尾に付く文字列を変更します。デフォルトは「 […]」です。
発火タイミング
自動生成された抜粋が短縮されるときに発火します。
シグネチャ
add_filter( 'excerpt_more', 'my_callback' ); // receives $moreクエリが実行される前に、それを変更します。アーカイブに表示される内容を変更する正しい方法で、2つ目の WP_Query を使うよりはるかに優れています。
発火タイミング
クエリ変数が解析された後、SQL が組み立てられる前に発火します。
シグネチャ
add_action( 'pre_get_posts', 'my_callback' ); // receives WP_Query $query (by reference)サンプル
add_action( 'pre_get_posts', function ( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return; // <- both guards are mandatory
}
if ( $query->is_category() ) {
$query->set( 'posts_per_page', 12 );
}
} );落とし穴
このフックは管理画面でも実行され、メニュー、ウィジェット、メディアライブラリを含むすべてのクエリで実行されます。is_admin() と is_main_query() のガードを省くと、管理画面の投稿一覧の表示を気づかないうちに変えてしまいます。原因を突き止めるのが本当に難しいバグです。また、$query を変更するだけにとどめ、何も return しないよう注意してください。
クエリの生の SQL の WHERE 句をフィルターします。
発火タイミング
クエリの SQL が組み立てられている最中に発火します。
シグネチャ
add_filter( 'posts_where', 'my_callback', 10, 2 ); // receives $where, WP_Query $query落とし穴
ここでは生の SQL を書くことになります。必ず $query->is_main_query() でガードし、ユーザー入力には必ず $wpdb->prepare() を使いましょう。これは WordPress サイトに SQL インジェクションを持ち込む最も手っ取り早い方法でもあります。
クエリが見つけた投稿の総数をフィルターします。これはページネーションの計算元になる値です。
発火タイミング
クエリが実行された後、ページネーションが計算される前に発火します。
シグネチャ
add_filter( 'found_posts', 'my_callback', 10, 2 ); // receives $found_posts, WP_Query $queryこの画素サイズを超えると、WordPress がアップロード画像を縮小し、元画像の代わりに「-scaled」版を配信します。そのしきい値を設定します。デフォルトは2560です。
発火タイミング
アップロード時、WordPress が画像を「大きい」と判定するときに発火します。
シグネチャ
add_filter( 'big_image_size_threshold', 'my_callback' ); // receives int $thresholdサンプル
// Serve originals at full resolution — no -scaled copy.
add_filter( 'big_image_size_threshold', '__return_false' );
// Or just raise the ceiling:
add_filter( 'big_image_size_threshold', function () {
return 3840;
} );落とし穴
これは「WordPress にアップロードしたら画像がぼやけて見える」という現象の最も多い原因で、その存在を知っている人はほとんどいません。元画像はディスク上にまだ残っていますが、単に配信されないだけです。これは最も長い辺に適用され、フィルターが有効になった後にアップロードした画像にのみ影響することに注意してください。
WordPress がアップロードに対して生成しようとしている画像サイズの配列をフィルターします。サイズを unset すると、その生成を止められます。
発火タイミング
アップロード時、派生ファイルが作成される前に発火します。
シグネチャ
add_filter( 'intermediate_image_sizes_advanced', 'my_callback', 10, 2 ); // receives $sizes, $metadataサンプル
add_filter( 'intermediate_image_sizes_advanced', function ( $sizes ) {
unset( $sizes['1536x1536'] );
unset( $sizes['2048x2048'] );
return $sizes;
} );落とし穴
テーマが実際に使っているサイズを削除すると、WordPress はフルサイズの元画像にフォールバックしてしまい、節約したディスク容量よりも大きな損失になります。また、これは新しいファイルの生成を止めるだけで、既存のファイルは再生成するまで残ります。
WordPress がアップロード画像を再エンコードするときの JPEG 品質を設定します。デフォルトは82です。
発火タイミング
WordPress が JPEG を書き出すたびに発火します。
シグネチャ
add_filter( 'jpeg_quality', 'my_callback', 10, 2 ); // receives $quality, $context落とし穴
品質82は写真には十分ですが、スクリーンショット、ロゴ、フラットなグラフィックには明らかに不十分です。これらははっきりした輪郭を持ち、圧縮ノイズを隠せる写真的なノイズがないためです。また、wp_editor_set_quality はより新しいフィルターで、画像エディタークラスを直接カバーします。両方を設定するのが一般的です。
WP_Image_Editor クラス(GD と Imagick)が使う出力品質を設定します。
発火タイミング
画像エディターのインスタンスが品質を設定するときに発火します。
シグネチャ
add_filter( 'wp_editor_set_quality', 'my_callback', 10, 2 ); // receives $quality, $mime_typeカスタム画像サイズを、メディアモーダルとブロックエディターのサイズ選択ドロップダウンに追加します。
発火タイミング
メディア UI がサイズ選択メニューを構築するときに発火します。
シグネチャ
add_filter( 'image_size_names_choose', 'my_callback' ); // receives $sizesサンプル
add_filter( 'image_size_names_choose', function ( $sizes ) {
return array_merge( $sizes, array( 'card' => __( 'Card', 'textdomain' ) ) );
} );落とし穴
add_image_size() はサイズを登録しますが、エディターで選択可能にはしません。「カスタム画像サイズがドロップダウンに表示されない」という質問は、すべてこのフィルターが欠けていることが原因です。
ファイルが uploads フォルダーに移動される前に、そのファイルを検査したり拒否したりします。
発火タイミング
アップロード中、ファイルが書き込まれる前に発火します。
シグネチャ
add_filter( 'wp_handle_upload_prefilter', 'my_callback' ); // receives $file落とし穴
ファイルを拒否するには、$file['error'] にメッセージ文字列を設定して $file を return します。false を返したり例外を投げたりしても、期待どおりには動きません。
添付ファイルの処理後に、(生成されたサイズを含む)メタデータの配列をフィルターします。
発火タイミング
アップロード時に派生画像が作成された後に発火します。
シグネチャ
add_filter( 'wp_generate_attachment_metadata', 'my_callback', 10, 2 ); // receives $metadata, $attachment_id落とし穴
これは画像最適化プラグインが使うフックです。すべての画像サイズが書き出された後に実行されるため、処理が遅くなることがあります。ここで HTTP リクエストを行うと、すべてのアップロードがそれを待つことになります。
WordPress がレスポンシブ画像用に生成する srcset の候補をフィルターします。
発火タイミング
レスポンシブ画像がレンダリングされるときに発火します。
シグネチャ
add_filter( 'wp_calculate_image_srcset', 'my_callback', 10, 5 );落とし穴
Removing the medium_large (768w) size elsewhere silently degrades srcset — that size exists almost entirely to serve it.
このフックの正確な引数の数を WordPress のソースと照合していません。頼りにする前に developer.wordpress.org で確認してください。不確かさをこっそり隠して推測を事実として示すよりも、はっきり明示することにしています。
管理メニューとサブメニューのページを登録します。
発火タイミング
管理メニューが構築されるときに発火します。
シグネチャ
add_action( 'admin_menu', 'my_callback' );サンプル
add_action( 'admin_menu', function () {
add_options_page(
'My Plugin',
'My Plugin',
'manage_options', // capability — NOT a role
'my-plugin',
'my_render_settings_page'
);
} );落とし穴
capability の引数は権限(capability)であって、権限グループ(role)ではありません。「administrator」を渡すと一見動いているように見えますが(一部の環境では管理者がその名前の権限を持っているため)、気づかないうちに不適切な人にアクセスを許してしまいます。manage_options を使いましょう。
管理画面の上部に通知を表示します。
発火タイミング
管理画面のページレンダリング時に発火します。
シグネチャ
add_action( 'admin_notices', 'my_callback' );落とし穴
このフックはすべての管理画面で発火します。すべての画面で無条件に「インストールありがとうございます!」という通知を表示するプラグインは、WordPress 管理画面で最も嫌われるパターンです。ガードを付け、閉じられるようにしましょう。
投稿が作成または更新されるたびに実行されます。メタボックスのデータを保存する一般的な場所です。
発火タイミング
投稿がデータベースに書き込まれた後に発火します。
シグネチャ
add_action( 'save_post', 'my_callback', 10, 3 ); // receives $post_id, $post, $updateサンプル
add_action( 'save_post', function ( $post_id ) {
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
if ( wp_is_post_revision( $post_id ) ) return;
if ( ! current_user_can( 'edit_post', $post_id ) ) return;
// ... now it is safe to save
}, 10, 1 );落とし穴
このフックは、実際の保存だけでなく、自動保存やリビジョンでも発火します。上記の3つのガードがないと、エディターが自動保存するたびにメタが空の値で上書きされてしまいます。データがランダムに消えているように見えるバグです。
投稿編集画面にメタボックスを登録します。
発火タイミング
編集画面が構築されるときに発火します。
シグネチャ
add_action( 'add_meta_boxes', 'my_callback', 10, 2 ); // receives $post_type, $post落とし穴
クラシックなメタボックスは、ブロックエディターが互換モードにフォールバックしない限り、ブロックエディターには表示されません。ブロックエディターネイティブなサイトでは、代わりに show_in_rest を付けて投稿メタを登録し、サイドバーパネルを作りましょう。
ユーザーがログインに成功した後に実行されます。
発火タイミング
認証に成功したときに発火します。
シグネチャ
add_action( 'wp_login', 'my_callback', 10, 2 ); // receives $user_login, WP_User $user新しいユーザーが作成された直後に実行されます。
発火タイミング
ユーザー登録時に発火します。
シグネチャ
add_action( 'user_register', 'my_callback', 10, 2 ); // receives $user_id, $userdata認証結果をフィルターします。ログインをブロックするには WP_Error を返します。
発火タイミング
ログインの試行中に発火します。
シグネチャ
add_filter( 'authenticate', 'my_callback', 30, 3 ); // receives $user, $username, $password落とし穴
ここでは優先度が非常に重要です。WordPress コアは独自のチェックを優先度20と30でフックしています。早すぎるタイミングで登録すると、パスワードがチェックされる前に処理が実行されてしまいます。
REST のルートとフィールドを登録します。
発火タイミング
REST API が初期化されるときに発火します。
シグネチャ
add_action( 'rest_api_init', 'my_callback' );サンプル
add_action( 'rest_api_init', function () {
register_rest_route( 'myplugin/v1', '/items', array(
'methods' => 'GET',
'callback' => 'my_get_items',
'permission_callback' => '__return_true', // BE DELIBERATE ABOUT THIS
) );
} );落とし穴
permission_callback は必須です。WP 5.5 以降は省略すると通知が出ますし、__return_true に設定するとエンドポイントが完全に公開されてしまいます。本当に公開してよいデータなら問題ありませんが、それ以外では深刻な穴になります。デフォルト任せにせず、自分で判断しましょう。
wp_schedule_event() 用のカスタムな繰り返し間隔を追加します。
発火タイミング
WordPress が利用可能なスケジュールの一覧を構築するときに発火します。
シグネチャ
add_filter( 'cron_schedules', 'my_callback' ); // receives $schedulesサンプル
add_filter( 'cron_schedules', function ( $schedules ) {
$schedules['every_five_minutes'] = array(
'interval' => 300, // seconds
'display' => __( 'Every 5 minutes', 'textdomain' ),
);
return $schedules;
} );落とし穴
WP-Cron は本物の cron ではありません。誰かがサイトを訪れたときにのみ発火するため、アクセスの少ないサイトでは5分間隔のスケジュールが5分ごとには実行されません。タイミングが本当に重要な場合は、WP-Cron を無効化し(DISABLE_WP_CRON)、本物のシステム cron から wp-cron.php を呼び出しましょう。
コメントが保存された直後に実行されます。
発火タイミング
コメントの送信時に発火します。
シグネチャ
add_action( 'comment_post', 'my_callback', 10, 3 ); // receives $comment_id, $approved, $commentdataコメントデータが保存される前にフィルターします。スパムチェックやバリデーションに使います。
発火タイミング
コメントが書き込まれる前に発火します。
シグネチャ
add_filter( 'preprocess_comment', 'my_callback' ); // receives $commentdata落とし穴
ここでコメントを拒否するには、メッセージを添えて wp_die() を呼び出します。false を返しても止まりません。
決済が成功した後、注文完了ページで実行されます。
発火タイミング
顧客がサンクスページ(注文完了ページ)に到達したときに発火します。
シグネチャ
add_action( 'woocommerce_thankyou', 'my_callback' ); // receives $order_id落とし穴
ここは注文処理(フルフィルメント)を確実に起動する場所ではありません。顧客が実際にサンクスページに到達した場合にのみ発火するため、支払い後にタブを閉じられると一度も実行されません。必ず実行しなければならない処理には、woocommerce_payment_complete か注文ステータスの遷移フックを使いましょう。
商品ページで、カートに追加ボタンの直前にマークアップを出力します。
発火タイミング
商品ページがレンダリングされている最中に発火します。
シグネチャ
add_action( 'woocommerce_before_add_to_cart_button', 'my_callback' );クラシックなチェックアウトで、フィールドを追加・削除・並べ替えします。
発火タイミング
チェックアウトフォームが構築されるときに発火します。
シグネチャ
add_filter( 'woocommerce_checkout_fields', 'my_callback' ); // receives $fields落とし穴
これはクラシック(ショートコード)版のチェックアウトにのみ影響します。新しいブロックベースのチェックアウトはこれを完全に無視し、JavaScript の Slot & Fill でカスタマイズします。これは初めてのときにほぼ全員がつまずくポイントです。
hook:script_loader_tag:whatItDoes
発火タイミング
hook:script_loader_tag:whenItFires
シグネチャ
add_filter( 'script_loader_tag', 'my_callback', 10, 3 ); // receives $tag, $handle, $srcサンプル
add_filter( 'script_loader_tag', function ( $tag, $handle, $src ) {
if ( 'my-script' !== $handle ) {
return $tag; // only touch our own handle
}
return str_replace( ' src=', ' defer src=', $tag );
}, 10, 3 );落とし穴
hook:script_loader_tag:gotcha
hook:style_loader_tag:whatItDoes
発火タイミング
hook:style_loader_tag:whenItFires
シグネチャ
add_filter( 'style_loader_tag', 'my_callback', 10, 4 ); // receives $tag, $handle, $href, $mediaサンプル
add_filter( 'style_loader_tag', function ( $tag, $handle ) {
if ( 'my-nonessential' !== $handle ) {
return $tag;
}
return str_replace( "media='all'", "media='print' onload=\"this.media='all'\"", $tag );
}, 10, 4 );落とし穴
hook:style_loader_tag:gotcha
hook:wp_default_scripts:whatItDoes
発火タイミング
hook:wp_default_scripts:whenItFires
シグネチャ
add_action( 'wp_default_scripts', 'my_callback' ); // receives WP_Scripts $scripts (by reference)サンプル
add_action( 'wp_default_scripts', function ( $scripts ) {
if ( is_admin() ) {
return; // never touch admin scripts
}
// Drop jQuery Migrate from the jquery bundle.
if ( ! empty( $scripts->registered['jquery'] ) ) {
$scripts->registered['jquery']->deps = array_diff(
$scripts->registered['jquery']->deps,
array( 'jquery-migrate' )
);
}
} );落とし穴
hook:wp_default_scripts:gotcha
hook:login_enqueue_scripts:whatItDoes
発火タイミング
hook:login_enqueue_scripts:whenItFires
シグネチャ
add_action( 'login_enqueue_scripts', 'my_callback' );サンプル
add_action( 'login_enqueue_scripts', function () {
wp_enqueue_style(
'my-login',
get_stylesheet_directory_uri() . '/login.css',
array(),
wp_get_theme()->get( 'Version' )
);
} );落とし穴
hook:login_enqueue_scripts:gotcha
hook:enqueue_block_assets:whatItDoes
発火タイミング
hook:enqueue_block_assets:whenItFires
シグネチャ
add_action( 'enqueue_block_assets', 'my_callback' );サンプル
add_action( 'enqueue_block_assets', function () {
wp_enqueue_style(
'my-block-shared',
plugins_url( 'block.css', __FILE__ ),
array(),
'1.0'
);
} );落とし穴
hook:enqueue_block_assets:gotcha
hook:wp_resource_hints:whatItDoes
発火タイミング
hook:wp_resource_hints:whenItFires
シグネチャ
add_filter( 'wp_resource_hints', 'my_callback', 10, 2 ); // receives $urls, $relation_typeサンプル
add_filter( 'wp_resource_hints', function ( $urls, $relation_type ) {
if ( 'dns-prefetch' === $relation_type ) {
$urls = array_diff( wp_dependencies_unique_hosts(), $urls );
}
return $urls;
}, 10, 2 );落とし穴
hook:wp_resource_hints:gotcha
このフックの正確な引数の数を WordPress のソースと照合していません。頼りにする前に developer.wordpress.org で確認してください。不確かさをこっそり隠して推測を事実として示すよりも、はっきり明示することにしています。
hook:wp_insert_post_data:whatItDoes
発火タイミング
hook:wp_insert_post_data:whenItFires
シグネチャ
add_filter( 'wp_insert_post_data', 'my_callback', 10, 2 ); // receives $data, $postarrサンプル
add_filter( 'wp_insert_post_data', function ( $data, $postarr ) {
if ( 'post' === $data['post_type'] && '' === trim( $data['post_title'] ) ) {
$data['post_title'] = 'Untitled ' . current_time( 'Y-m-d' );
}
return $data;
}, 10, 2 );落とし穴
hook:wp_insert_post_data:gotcha
hook:wp_after_insert_post:whatItDoes
発火タイミング
hook:wp_after_insert_post:whenItFires
シグネチャ
add_action( 'wp_after_insert_post', 'my_callback', 10, 4 ); // receives $post_id, WP_Post $post, $update, $post_beforeサンプル
add_action( 'wp_after_insert_post', function ( $post_id, $post, $update, $post_before ) {
if ( 'post' !== $post->post_type || wp_is_post_revision( $post_id ) ) {
return;
}
// Safe: meta is written by now.
$price = get_post_meta( $post_id, 'price', true );
}, 10, 4 );落とし穴
hook:wp_after_insert_post:gotcha
hook:transition_post_status:whatItDoes
発火タイミング
hook:transition_post_status:whenItFires
シグネチャ
add_action( 'transition_post_status', 'my_callback', 10, 3 ); // receives $new_status, $old_status, WP_Post $postサンプル
add_action( 'transition_post_status', function ( $new, $old, $post ) {
if ( 'publish' !== $new || 'publish' === $old ) {
return; // already published: this is just an edit
}
if ( 'post' !== $post->post_type ) {
return;
}
my_send_new_post_notification( $post->ID );
}, 10, 3 );落とし穴
hook:transition_post_status:gotcha
hook:{$new_status}_{$post_type}:whatItDoes
発火タイミング
hook:{$new_status}_{$post_type}:whenItFires
シグネチャ
add_action( 'publish_post', 'my_callback', 10, 2 ); // dynamic: publish_page, publish_book, draft_post…サンプル
// Fires for a custom post type 'book' entering publish.
add_action( 'publish_book', function ( $post_id, $post ) {
my_ping_index( $post_id );
}, 10, 2 );落とし穴
hook:{$new_status}_{$post_type}:gotcha
このフックの正確な引数の数を WordPress のソースと照合していません。頼りにする前に developer.wordpress.org で確認してください。不確かさをこっそり隠して推測を事実として示すよりも、はっきり明示することにしています。
hook:posts_clauses:whatItDoes
発火タイミング
hook:posts_clauses:whenItFires
シグネチャ
add_filter( 'posts_clauses', 'my_callback', 10, 2 ); // receives array $clauses, WP_Query $queryサンプル
add_filter( 'posts_clauses', function ( $clauses, $query ) {
if ( is_admin() || ! $query->is_main_query() || ! $query->is_post_type_archive( 'book' ) ) {
return $clauses;
}
global $wpdb;
$clauses['join'] .= " INNER JOIN {$wpdb->postmeta} pm ON pm.post_id = {$wpdb->posts}.ID AND pm.meta_key = 'rating' ";
$clauses['orderby'] = ' pm.meta_value+0 DESC ';
return $clauses;
}, 10, 2 );落とし穴
hook:posts_clauses:gotcha
hook:the_posts:whatItDoes
発火タイミング
hook:the_posts:whenItFires
シグネチャ
add_filter( 'the_posts', 'my_callback', 10, 2 ); // receives array $posts, WP_Query $queryサンプル
add_filter( 'the_posts', function ( $posts, $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return $posts;
}
return array_values( array_filter( $posts, function ( $p ) {
return ! get_post_meta( $p->ID, 'hidden', true );
} ) );
}, 10, 2 );落とし穴
hook:the_posts:gotcha
hook:admin_bar_menu:whatItDoes
発火タイミング
hook:admin_bar_menu:whenItFires
シグネチャ
add_action( 'admin_bar_menu', 'my_callback', 100 ); // receives WP_Admin_Bar $wp_admin_bar (by reference)サンプル
add_action( 'admin_bar_menu', function ( $wp_admin_bar ) {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$wp_admin_bar->add_node( array(
'id' => 'purge-cache',
'title' => 'Purge cache',
'href' => wp_nonce_url( admin_url( 'admin-post.php?action=purge_cache' ), 'purge_cache' ),
) );
}, 100 ); // core's own nodes are added at priorities up to ~80落とし穴
hook:admin_bar_menu:gotcha
hook:plugin_action_links_{$plugin_file}:whatItDoes
発火タイミング
hook:plugin_action_links_{$plugin_file}:whenItFires
シグネチャ
add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'my_callback' ); // receives $actionsサンプル
add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), function ( $actions ) {
array_unshift( $actions, sprintf(
'<a href="%s">%s</a>',
esc_url( admin_url( 'options-general.php?page=my-plugin' ) ),
esc_html__( 'Settings', 'textdomain' )
) );
return $actions;
} );落とし穴
hook:plugin_action_links_{$plugin_file}:gotcha
hook:manage_{$post_type}_posts_columns:whatItDoes
発火タイミング
hook:manage_{$post_type}_posts_columns:whenItFires
シグネチャ
add_filter( 'manage_book_posts_columns', 'my_callback' ); // receives $columnsサンプル
add_filter( 'manage_book_posts_columns', function ( $columns ) {
$date = $columns['date'];
unset( $columns['date'] );
$columns['isbn'] = __( 'ISBN', 'textdomain' );
$columns['date'] = $date; // put Date back on the end
return $columns;
} );落とし穴
hook:manage_{$post_type}_posts_columns:gotcha
hook:manage_{$post_type}_posts_custom_column:whatItDoes
発火タイミング
hook:manage_{$post_type}_posts_custom_column:whenItFires
シグネチャ
add_action( 'manage_book_posts_custom_column', 'my_callback', 10, 2 ); // receives $column, $post_idサンプル
add_action( 'manage_book_posts_custom_column', function ( $column, $post_id ) {
if ( 'isbn' === $column ) {
echo esc_html( get_post_meta( $post_id, 'isbn', true ) );
}
}, 10, 2 );落とし穴
hook:manage_{$post_type}_posts_custom_column:gotcha
hook:admin_body_class:whatItDoes
発火タイミング
hook:admin_body_class:whenItFires
シグネチャ
add_filter( 'admin_body_class', 'my_callback' ); // receives $classesサンプル
add_filter( 'admin_body_class', function ( $classes ) {
$screen = get_current_screen();
if ( $screen && 'book' === $screen->post_type ) {
$classes .= ' my-book-screen'; // note the leading space
}
return $classes;
} );落とし穴
hook:admin_body_class:gotcha
hook:admin_post_{$action}:whatItDoes
発火タイミング
hook:admin_post_{$action}:whenItFires
シグネチャ
add_action( 'admin_post_my_action', 'my_callback' ); // no argumentsサンプル
add_action( 'admin_post_my_action', function () {
check_admin_referer( 'my_action' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'Nope.', 'textdomain' ), 403 );
}
update_option( 'my_thing', sanitize_text_field( wp_unslash( $_POST['my_thing'] ?? '' ) ) );
wp_safe_redirect( add_query_arg( 'updated', '1', admin_url( 'options-general.php?page=my-plugin' ) ) );
exit; // without this you get a blank white screen
} );落とし穴
hook:admin_post_{$action}:gotcha
hook:wp_ajax_{$action}:whatItDoes
発火タイミング
hook:wp_ajax_{$action}:whenItFires
シグネチャ
add_action( 'wp_ajax_my_action', 'my_callback' ); // $action = the 'action' param sent in the requestサンプル
add_action( 'wp_ajax_my_save_thing', function () {
check_ajax_referer( 'my_save_thing' ); // nonce, or anyone can call this
if ( ! current_user_can( 'edit_posts' ) ) {
wp_send_json_error( 'nope', 403 ); // capability != logged in
}
update_option( 'my_thing', sanitize_text_field( $_POST['value'] ) );
wp_send_json_success( array( 'saved' => true ) ); // dies for you
} );落とし穴
hook:wp_ajax_{$action}:gotcha
hook:wp_ajax_nopriv_{$action}:whatItDoes
発火タイミング
hook:wp_ajax_nopriv_{$action}:whenItFires
シグネチャ
add_action( 'wp_ajax_nopriv_my_action', 'my_callback' );サンプル
// Front-end AJAX has to be registered TWICE to work for everyone.
add_action( 'wp_ajax_my_public_thing', 'my_handler' );
add_action( 'wp_ajax_nopriv_my_public_thing', 'my_handler' );落とし穴
hook:wp_ajax_nopriv_{$action}:gotcha
hook:rest_authentication_errors:whatItDoes
発火タイミング
hook:rest_authentication_errors:whenItFires
シグネチャ
add_filter( 'rest_authentication_errors', 'my_callback' ); // receives WP_Error|null|true $errorsサンプル
add_filter( 'rest_authentication_errors', function ( $errors ) {
if ( ! empty( $errors ) ) {
return $errors; // someone already decided — do not stomp them
}
if ( ! is_user_logged_in() ) {
return new WP_Error( 'rest_forbidden', 'Login required.', array( 'status' => 401 ) );
}
return $errors;
} );落とし穴
hook:rest_authentication_errors:gotcha
hook:rest_pre_dispatch:whatItDoes
発火タイミング
hook:rest_pre_dispatch:whenItFires
シグネチャ
add_filter( 'rest_pre_dispatch', 'my_callback', 10, 3 ); // receives $result, WP_REST_Server $server, WP_REST_Request $requestサンプル
add_filter( 'rest_pre_dispatch', function ( $result, $server, $request ) {
if ( '/myplugin/v1/report' !== $request->get_route() ) {
return $result; // null = carry on normally
}
$cached = get_transient( 'my_report' );
return ( false === $cached ) ? $result : rest_ensure_response( $cached );
}, 10, 3 );落とし穴
hook:rest_pre_dispatch:gotcha
hook:rest_prepare_{$post_type}:whatItDoes
発火タイミング
hook:rest_prepare_{$post_type}:whenItFires
シグネチャ
add_filter( 'rest_prepare_post', 'my_callback', 10, 3 ); // receives WP_REST_Response $response, WP_Post $post, WP_REST_Request $requestサンプル
add_filter( 'rest_prepare_post', function ( $response, $post, $request ) {
$response->data['reading_time'] = (int) ceil( str_word_count( wp_strip_all_tags( $post->post_content ) ) / 200 );
return $response;
}, 10, 3 );落とし穴
hook:rest_prepare_{$post_type}:gotcha
hook:rest_{$post_type}_query:whatItDoes
発火タイミング
hook:rest_{$post_type}_query:whenItFires
シグネチャ
add_filter( 'rest_post_query', 'my_callback', 10, 2 ); // receives array $args, WP_REST_Request $requestサンプル
add_filter( 'rest_post_query', function ( $args, $request ) {
if ( $request->get_param( 'featured' ) ) {
$args['meta_key'] = 'is_featured';
$args['meta_value'] = '1';
}
return $args;
}, 10, 2 );落とし穴
hook:rest_{$post_type}_query:gotcha
このフックの正確な引数の数を WordPress のソースと照合していません。頼りにする前に developer.wordpress.org で確認してください。不確かさをこっそり隠して推測を事実として示すよりも、はっきり明示することにしています。