WordPress コード・タグ チートシート
目次
- 1 よく使うエスケープ関数 & 国際化
- 2 基本テンプレートタグ
- 3 条件分岐タグ(頻出)
- 4 WP_Query 基本パターン
- 5 ページネーション(シンプル)
- 6 メニュー出力
- 7 画像サイズの追加・出力
- 8 スクリプト/スタイルの読み込み
- 9 ショートコードの作成
- 10 カスタム投稿タイプ・タクソノミー
- 11 ACF(Advanced Custom Fields)出力例
- 12 パンくず(極シンプル)
- 13 Ajax(フロント→PHP)
- 14 セキュリティ(Nonce / sanitize / capability)
- 15 REST API エンドポイント追加
- 16 ユーザー/オプションAPI
- 17 ウィジェットエリア(サイドバー)
- 18 管理画面の投稿一覧:カラム追加
- 19 管理画面:クイックフィルタ(タクソノミ)
- 20 Cron(WP-Cron)
- 21 リダイレクト(テンプレート/ログイン)
- 22 リライトルール(任意URL→テンプレ)
- 23 Gutenberg ブロック(ショートコード的な最小例)
- 24 WooCommerce(よく使うフック/取得)
- 25 Contact Form 7(最小カスタム)
- 26 小ワザ集
- 27 付録: 代表的なフック早見
- 28 すぐに使える実装指針
よく使うエスケープ関数 & 国際化
// エスケープ(出力時)
echo esc_html( $text );
echo esc_attr( $value );
echo esc_url( $url );
wp_kses_post( $html ); // 許可タグのみ
// 翻訳
__( 'Text', 'textdomain' );
_e( 'Text', 'textdomain' );
printf( __( 'Hello %s', 'textdomain' ), esc_html( $name ) );JavaScript- 何をする? 出力時のXSS対策(
esc_html/esc_attr/esc_url/wp_kses_post)と翻訳関数(__/_e)。 - どこで使う? テンプレートやショートコードの返り値。
- 注意: 文字列は原則エスケープしてから出力。URLは
esc_url、属性はesc_attr。
基本テンプレートタグ
// ヘッダー/フッター/サイドバー
get_header();
get_footer();
get_sidebar();
// 別テンプレートの取り込み
get_template_part( 'template-parts/content', 'page' );
// タイトルや本文
if ( have_posts() ) :
while ( have_posts() ) : the_post();
the_title( '<h1>', '</h1>' );
the_content();
endwhile;
endif;
// アイキャッチ
if ( has_post_thumbnail() ) {
the_post_thumbnail( 'large', [ 'class' => 'cover' ] );
}
// パーマリンク
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>JavaScript- 何をする? 標準ループ、ヘッダー/フッター読込、アイキャッチ出力など。
- どこで?
single.php,page.php,archive.php等。 - 注意: ループ内外の関数の違い(
the_*はループ内、get_the_*は値を返す)。
条件分岐タグ(頻出)
if ( is_front_page() ) { /* TOP */ }
if ( is_home() ) { /* 投稿一覧 */ }
if ( is_singular('post') ) { /* 投稿詳細 */ }
if ( is_page('about') ) { /* 固定ページスラッグ */ }
if ( is_post_type_archive('news') ) { /* CPT アーカイブ */ }
if ( is_tax('genre') ) { /* タクソノミー */ }
if ( is_category('notice') ) { /* カテゴリ */ }
if ( is_tag('pickup') ) { /* タグ */ }
if ( is_404() ) { /* 404 */ }PHP- 何をする? 表示箇所ごとに処理やUIを切り替える。
- どこで? テンプレート、
template_redirect、ウィジェット表示制御など。 - 注意:
is_front_page()とis_home()の違い(固定フロントか、投稿一覧か)。
WP_Query 基本パターン
$args = [
'post_type' => 'post',
'posts_per_page' => 6,
'orderby' => 'date',
'order' => 'DESC',
'paged' => get_query_var('paged') ?: 1,
];
$q = new WP_Query( $args );
if ( $q->have_posts() ) :
echo '<ul class="posts">';
while ( $q->have_posts() ) : $q->the_post();
echo '<li><a href="'. esc_url( get_permalink() ) .'">'. esc_html( get_the_title() ) .'</a></li>';
endwhile;
echo '</ul>';
wp_reset_postdata();
endif;PHPカテゴリ/タクソ条件
$args['tax_query'] = [[
'taxonomy' => 'category',
'field' => 'slug',
'terms' => ['news','topics'],
]];PHP- 何をする? 任意条件で投稿を取得するカスタムループ。
- どこで? テンプレート部位(最新ニュース、特集など)。
- 注意:
wp_reset_postdata()を忘れない。pagedを渡すとページネーションが効く。
ページネーション(シンプル)
$big = 999999999;
echo paginate_links([
'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
'format' => '?paged=%#%',
'current' => max(1, get_query_var('paged')),
'total' => $q->max_num_pages ?? $wp_query->max_num_pages,
]);PHP- 何をする? 一覧のページ送り生成。
- どこで? 一覧テンプレートのフッター付近。
- 注意: カスタムクエリ使用時は
$q->max_num_pagesを渡す。
メニュー出力
// functions.php: 登録
register_nav_menus([
'global' => 'グローバルナビ',
'footer' => 'フッターナビ',
]);
// テンプレートで出力
wp_nav_menu([
'theme_location' => 'global',
'container' => 'nav',
'menu_class' => 'gnav',
]);PHP- 何をする? 管理画面で作ったメニューを任意位置に表示。
- どこで? ヘッダーやフッター。
- 注意: 先に
register_nav_menusでロケーション登録が必要。
画像サイズの追加・出力
// functions.php
add_theme_support( 'post-thumbnails' );
add_image_size( 'mv', 1920, 1080, true );
// テンプレート
if ( has_post_thumbnail() ) {
the_post_thumbnail( 'mv' );
}PHP- 何をする? サムネイルのカスタムサイズ定義と出力。
- どこで?
functions.phpで定義、テンプレでthe_post_thumbnail('mv')など。 - 注意: 既存画像は再生成が必要(Regenerate Thumbnails など)。
スクリプト/スタイルの読み込み
function my_enqueue_assets() {
wp_enqueue_style( 'main', get_stylesheet_directory_uri() . '/assets/css/main.css', [], '1.0' );
wp_enqueue_script( 'main', get_stylesheet_directory_uri() . '/assets/js/main.js', ['jquery'], '1.0', true );
}
add_action( 'wp_enqueue_scripts', 'my_enqueue_assets' );PHP- 何をする? CSS/JSの正しい登録と依存解決。
- どこで?
functions.php→wp_enqueue_scripts。 - 注意: 直書きではなく必ずenqueue。子テーマは
get_stylesheet_directory_uri()。
ショートコードの作成
function sc_btn( $atts, $content = '' ) {
$a = shortcode_atts([
'url' => '#',
'type' => 'primary',
], $atts, 'btn' );
return '<a class="btn btn-'. esc_attr($a['type']) .'" href="'. esc_url($a['url']) .'">'. esc_html($content) .'</a>';
}
add_shortcode( 'btn', 'sc_btn' );
// 使い方: [btn url="/contact/" type="secondary"]お問い合わせ[/btn]PHP- 何をする?
[btn]のような簡易UI部品をコンテンツ内で呼べるようにする。 - どこで?
functions.php。 - 注意: 返り値はHTML文字列。エスケープを忘れずに。
カスタム投稿タイプ・タクソノミー
// CPT: news
function cpt_news() {
register_post_type( 'news', [
'label' => 'お知らせ',
'public' => true,
'has_archive' => true,
'menu_position' => 5,
'menu_icon' => 'dashicons-megaphone',
'supports' => [ 'title','editor','thumbnail','excerpt','custom-fields' ],
'show_in_rest' => true,
]);
}
add_action( 'init', 'cpt_news' );
// Tax: genre
function tax_genre() {
register_taxonomy( 'genre', 'news', [
'label' => 'ジャンル',
'hierarchical' => true,
'show_in_rest' => true,
]);
}
add_action( 'init', 'tax_genre' );PHP- 何をする? 例:
news投稿タイプ、genreタクソノミー。 - どこで?
functions.phpのinitフック。 - 注意:
show_in_restをtrueにするとGutenbergやREST活用が容易。
ACF(Advanced Custom Fields)出力例
// テンプレートで
$title_sub = get_field('title_sub');
if ( $title_sub ) {
echo '<p class="subtitle">' . esc_html( $title_sub ) . '</p>';
}
// 画像フィールド
$img = get_field('kv_image');
if ( !empty($img) ) {
echo '<img src="'. esc_url($img['url']) .'" alt="'. esc_attr($img['alt']) .'">';
}PHP- 何をする?
get_field()で任意フィールド/画像を出力。 - どこで? 該当テンプレート。
- 注意: 値がない時の分岐、画像は
url/altをエスケープ。
パンくず(極シンプル)
function the_breadcrumb() {
echo '<nav class="breadcrumb"><a href="'. esc_url(home_url('/')) .'">HOME</a>';
if ( is_category() || is_single() ) {
echo ' » ' . get_the_category_list(', ');
if ( is_single() ) echo ' » ' . esc_html( get_the_title() );
} elseif ( is_page() ) {
echo ' » ' . esc_html( get_the_title() );
}
echo '</nav>';
}PHP- 何をする? シンプルなパンくずを自前実装。
- どこで? テンプレート共通パーツ。
- 注意: 複雑なサイトはBreadcrumb NavXT等のプラグイン検討。
Ajax(フロント→PHP)
// JS 側(enqueue した main.js 等)
fetch( window.wp_data.ajax_url, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({ action: 'hello', name: 'Yokota', _ajax_nonce: window.wp_data.nonce })
}).then(r=>r.json()).then(console.log);
// PHP 側(functions.php)
function my_localize() {
wp_localize_script( 'main', 'wp_data', [
'ajax_url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce('my_nonce')
]);
}
add_action( 'wp_enqueue_scripts', 'my_localize' );
function ajax_hello() {
check_ajax_referer('my_nonce');
wp_send_json([ 'message' => 'Hello, ' . sanitize_text_field($_POST['name'] ?? '') ]);
}
add_action( 'wp_ajax_hello', 'ajax_hello' );
add_action( 'wp_ajax_nopriv_hello', 'ajax_hello' );PHP- 何をする? JSから
admin-ajax.phpへPOSTし、JSONを返す。 - どこで?
functions.phpでハンドラ登録、JSでfetch。 - 注意:
check_ajax_refererでnonce検証必須。wp_localize_scriptで値を渡す。
セキュリティ(Nonce / sanitize / capability)
// フォーム(テンプレート)
wp_nonce_field( 'save_profile', 'profile_nonce' );
// 受け取り(プラグイン/テーマ)
if ( ! isset($_POST['profile_nonce']) || ! wp_verify_nonce( $_POST['profile_nonce'], 'save_profile' ) ) {
wp_die( 'Invalid nonce' );
}
if ( ! current_user_can('edit_posts') ) {
wp_die( '権限がありません' );
}
$name = sanitize_text_field( $_POST['name'] ?? '' );PHP- 何をする?
wp_nonce_field/wp_verify_nonce、current_user_can、sanitize_*。 - どこで? フォーム保存や管理系機能。
- 注意: 保存前にサニタイズ、出力時にエスケープが原則。
REST API エンドポイント追加
add_action( 'rest_api_init', function() {
register_rest_route( 'mysite/v1', '/latest', [
'methods' => 'GET',
'callback' => function( WP_REST_Request $req ) {
$q = new WP_Query([ 'post_type' => 'post', 'posts_per_page' => 3 ]);
$items = [];
while ( $q->have_posts() ) { $q->the_post();
$items[] = [ 'title' => get_the_title(), 'url' => get_permalink() ];
}
wp_reset_postdata();
return rest_ensure_response( $items );
}
]);
});PHP- 何をする?
register_rest_routeで独自エンドポイントを作成。 - どこで?
rest_api_initフック。 - 注意: 返り値は
rest_ensure_response、必要なら認可チェックを入れる。
ユーザー/オプションAPI
// 現在のユーザー
$user = wp_get_current_user();
if ( $user->exists() ) {
echo esc_html( $user->display_name );
}
// オプション保存/取得
update_option( 'company_tel', '092-xxx-xxxx' );
echo esc_html( get_option( 'company_tel', '' ) );PHP- 何をする? ログインユーザー取得、
update_option/get_optionでサイト設定保存。 - どこで? 管理ページやフロント。
- 注意: オプションはサイト全体設定向き。大量データは不向き。
ウィジェットエリア(サイドバー)
// functions.php
function my_widgets() {
register_sidebar([
'name' => 'サイドバー',
'id' => 'sidebar-1',
'before_widget' => '<section class="widget">',
'after_widget' => '</section>',
'before_title' => '<h2>',
'after_title' => '</h2>',
]);
}
add_action( 'widgets_init', 'my_widgets' );
// テンプレート
if ( is_active_sidebar('sidebar-1') ) { dynamic_sidebar('sidebar-1'); }PHP- 何をする? サイドバー等のドロップイン領域を追加。
- どこで?
widgets_init→register_sidebar、テンプレでdynamic_sidebar。 - 注意: マークアップの
before_*/after_*でテーマに合わせる。
管理画面の投稿一覧:カラム追加
// カラム追加
a dd_filter( 'manage_post_posts_columns', function( $cols ) {
$cols['thumb'] = 'サムネ';
return $cols;
});
add_action( 'manage_post_posts_custom_column', function( $col, $post_id ) {
if ( 'thumb' === $col ) {
echo get_the_post_thumbnail( $post_id, [60,60] );
}
}, 10, 2 );PHP- 何をする? 管理画面一覧に独自カラム(例:サムネ)を表示。
- どこで?
manage_*_posts_columns&manage_*_posts_custom_column。 - 注意: 大量行で重い処理は避ける(N+1回避)。
管理画面:クイックフィルタ(タクソノミ)
add_action( 'restrict_manage_posts', function() {
global $typenow;
if ( 'news' !== $typenow ) return;
$taxonomy = 'genre';
wp_dropdown_categories([
'show_option_all' => 'すべてのジャンル',
'taxonomy' => $taxonomy,
'name' => $taxonomy,
'orderby' => 'name',
'selected' => $_GET[$taxonomy] ?? '',
'hierarchical' => true,
'show_count' => true,
'hide_empty' => false,
]);
});PHP- 何をする? 投稿一覧上部にドロップダウンでタクソ絞り込み。
- どこで?
restrict_manage_postsフック。 - 注意:
$typenowで対象CPTを限定。
Cron(WP-Cron)
// 毎時イベント登録(有効化時)
register_activation_hook( __FILE__, function(){
if ( ! wp_next_scheduled( 'my_hourly_event' ) ) {
wp_schedule_event( time(), 'hourly', 'my_hourly_event' );
}
});
add_action( 'my_hourly_event', function(){
// ここに定期処理
});PHP- 何をする? 毎時などの定期処理を登録。
- どこで? プラグイン/テーマ。
register_activation_hookでスケジュール。 - 注意: トラフィック依存。正確さ重視ならサーバーCronで
wp-cron.php呼び出し。
リダイレクト(テンプレート/ログイン)
add_action( 'template_redirect', function() {
if ( is_page('old-page') ) {
wp_redirect( home_url('/new-page/'), 301 );
exit;
}
});
// ログイン後の遷移
add_filter( 'login_redirect', function( $redirect_to, $request, $user ) {
return admin_url('edit.php?post_type=news');
}, 10, 3 );PHP- 何をする? 特定ページを別URLへ301、ログイン後の遷移変更。
- どこで?
template_redirect/login_redirect。 - 注意:
wp_redirect後はexit必須。無限ループに注意。
リライトルール(任意URL→テンプレ)
add_action( 'init', function() {
add_rewrite_rule( '^campaign/([0-9]+)/?$', 'index.php?campaign_id=$matches[1]', 'top' );
add_rewrite_tag( '%campaign_id%', '([0-9]+)' );
});
add_action( 'template_redirect', function(){
if ( get_query_var('campaign_id') ) {
// 専用テンプレを読み込むなど
include locate_template( 'page-campaign.php' );
exit;
}
});PHP- 何をする? 人間可読URL→クエリ変数→専用テンプレ読込。
- どこで?
initでadd_rewrite_rule。add_rewrite_tagで変数登録。 - 注意: 追加後はパーマリンク再生成(設定を保存)または
flush_rewrite_rules()(有効化時のみ)。
Gutenberg ブロック(ショートコード的な最小例)
// functions.php(超簡易:Blocks API v2 ベースではなくショートコード流用)
add_action( 'init', function(){
register_block_type( 'mysite/btn', [
'render_callback' => function( $attrs, $content ) {
$url = esc_url( $attrs['url'] ?? '#' );
$text = esc_html( $attrs['text'] ?? 'Button' );
return '<a class="wp-block-btn__link" href="'. $url .'">'. $text .'</a>';
}
]);
});PHP- 何をする? 属性からボタンをレンダリングする極小ブロック。
- どこで?
register_block_type。 - 注意: 本格実装は
block.jsonやエディタJSが必要。まずは「ショートコードの代替」として。
WooCommerce(よく使うフック/取得)
// 商品ループ内に在庫有無を表示
add_action( 'woocommerce_after_shop_loop_item_title', function(){
global $product;
echo wc_get_stock_html( $product );
}, 15 );
// カートアイテム数を取得
echo WC()->cart ? WC()->cart->get_cart_contents_count() : 0;
// 単一商品ページのタブ追加
add_filter( 'woocommerce_product_tabs', function( $tabs ){
$tabs['spec'] = [
'title' => '仕様',
'priority' => 50,
'callback' => function(){ echo '<h2>仕様</h2><p>ここに仕様</p>'; }
];
return $tabs;
});PHP- 何をする? ループ内に在庫表示、カート数取得、商品タブ追加など。
- どこで? 子テーマ
functions.php(更新に強い)。 - 注意:
global $product;の有効範囲、カスタマイズはフック優先度を調整。
Contact Form 7(最小カスタム)
// 送信後にサンクスへ(グローバル)
add_action( 'wp_footer', function(){ ?>
<script>
document.addEventListener('wpcf7mailsent', function(e){
location.href = '/thanks/';
}, false);
</script>
<?php });PHP- 何をする? 送信完了イベントでサンクスページへ遷移。
- どこで?
wp_footerでスクリプト挿入 or 専用JS。 - 注意: 複数フォームやマルチステップと併用時は
if(e.detail.contactFormId===...)でフォームID判定を。
小ワザ集
// サムネイルの alt を自動でタイトルに\ nadd_filter( 'wp_get_attachment_image_attributes', function( $attr, $attachment ){
if ( empty($attr['alt']) ) $attr['alt'] = get_the_title($attachment->post_parent);
return $attr;
}, 10, 2 );
// 外部リンクに target/_blank 付与(the_content)
add_filter( 'the_content', function( $content ){
return preg_replace( '/<a(.*?)href=\"(http[^\"]+)\"(.*?)>/', '<a$1href="$2" target="_blank" rel="noopener"$3>', $content );
});
// 管理バーをフロントで非表示
add_filter( 'show_admin_bar', '__return_false' );PHP- 何をする? 画像
alt自動補完、外部リンク自動_blank、管理バー非表示など。 - どこで?
functions.php。 - 注意:
the_contentの正規表現は副作用が出やすい。必要に応じてHTMLパーサの利用も検討。
付録: 代表的なフック早見
アクション: init, template_redirect, wp_enqueue_scripts, widgets_init, pre_get_posts, save_post, rest_api_init, woocommerce_* など
フィルター: the_content, excerpt_more, upload_mimes, login_redirect, body_class, post_class など
- 何をする? どのタイミングでコードが走るかの目安。
使い方のコツ: 画面描画前はtemplate_redirect、読み込みはwp_enqueue_scripts、保存系はsave_post、RESTはrest_api_init。
すぐに使える実装指針
- 子テーマ化:親テーマ更新対策として、PHP/JS/CSSは子テーマに集約。
- エスケープ原則:保存→sanitize、出力→escape。フォーム/CF7拡張やACF出力で徹底。
- 分離:レイアウトはテンプレ、ロジックは関数(
inc/*.php)に分離。functions.phpは入口だけ。 - 高速化:画像サイズ設計(
add_image_size)、不要スクリプトのwp_dequeue_script、遅延読み込み。 - Woo/CF7/ACF:フックベースで最小限オーバーライド。直接テンプレを触る前に「フックある?」の発想。