テーマに直接ショートコードを登録し、安全に配信し、適切な場所にレンダリングする方法を具体的に紹介しよう。 ワードプレステーマ 明確な構造、クリーンなコード、そして高速なロード時間を持つテーマです。実用的な例を提供し、テンプレート内のdo_shortcodeについて説明し、属性、エスケープ、キャッシュについて議論し、長期的に保守可能なテーマのためのベストプラクティスを追加します。
中心点
- 登録 add_shortcodeとclearコールバック関数経由
- 統合 エディタ、ウィジェット、テンプレートでdo_shortcodeを使います。
- セキュリティ エスケープ、属性、バリデーション
- メンテナンス 子テーマ、ドキュメント、バージョン管理
- パフォーマンス キャッシュ、経済的なクエリ、キャッシュの無効化
テーマのショートコード:登録と構造
テーマへの登録は functions.php または、レイアウトから機能を分離したい場合は、小さなプラグインを使用する必要があります。各コールバック関数は文字列を返し、echoは使いません。プラグインとのコンフリクトを避けるため、ネーミングにはユニークな接頭辞を選んでいます。例えば、/inc/shortcodes.phpのように、functions.phpのrequire_onceをターゲットにしています。最初はシンプルな挨拶ショートコードで十分で、後で段階的に拡張していく。
<?php
// /wp-content/themes/my-theme/functions.php
require_once get_template_directory() .'/inc/shortcodes.php';
<?php
// /wp-content/themes/my-theme/inc/shortcodes.php
関数 my_greeting_shortcode() {
return 'こんにちは、私のウェブサイトへようこそ!
}
add_shortcode('greeting', 'my_greeting_shortcode');
テンプレートでショートコードを使う:do_shortcode
テンプレート内のショートコードを do_shortcode コンテンツをヘッダーやフッター、特別なテンプレートに統合するときに使います。こうすることで、エディターをすっきりさせ、繰り返し使うモジュールを一箇所にまとめておくことができる。私は、どのショートコードがここで実行されているのか他の人がすぐにわかるように、短いコメントでコード内のテンプレート呼び出しを文書化しています。動的パラメータについては、PHPでショートコードの文字列を作成し、値を安全にエスケープして渡している。この方法は、header.php、footer.php、page-templatesなどのすべてのテンプレートファイルで機能します。
<?php
// テンプレートファイル内
echo do_shortcode('[greeting]');
echo do_shortcode('[colorbox color="green"]ナイステキスト[/colorbox]');
属性、コンテンツ、セキュリティ
で属性を設定する。 ショートコード・アッツ を使用し、esc_html、esc_attr、esc_url で値を保護します。これにより、XSSを防ぎ、すべての出力で有効なHTMLを保証します。特定のタグだけを許可したい場合は、オプションでショートコードで囲まれたコンテンツをwp_ksesで扱います。色については、ホワイトリストの値のみを受け入れるか、正規表現でチェックし、スクリプトがすり抜けないようにしています。これらのルールにより、ショートコードは信頼性を保ち、予測可能な出力を提供します。
<?php
function my_colorbox_shortcode($atts, $content = null) {
$atts = shortcode_atts([
'color' => blue'、
], $atts, 'colorbox');
$color = preg_match('/^#?[0-9a-fA-F]{3,6}$/', $atts['color']) ?$atts['color'] : 'blue';
$inner = wp_kses($content, ['strong' => [], 'em' => [], 'a' => ['href' => []]);
$style = 'background:' . esc_attr($color) .';padding:10px';
return '<div style="' . $style . '">' .$inner .'</div>';
}
add_shortcode('colorbox', 'my_colorbox_shortcode');
実例:当年、ボタン、日付
私は小さなヘルパーショートコードを、次のような定期的なコンテンツに使用している。 年ボタンやカスタム投稿タイプからのリスト。年のショートコードを使えば、フッターやテキストブロックのメンテナンス作業が省ける。編集者がコードを変更することなく作業できるように、ボタンにテキスト、URL、色を持たせている。CPTからのデータ出力については、クエリーを制限し、結果をキャッシュすることで、ページを高速に保つようにしている。以下は、その基礎となる3つの短いスニペットである。
<?php
// Jahr
add_shortcode('current-year', function() {
return date('Y');
});
// Button
add_shortcode('button', function($atts) {
$atts = shortcode_atts([
'text' => '今すぐクリック'、
'url' => '#'、
'color' => '#2d89ef'、
], $atts, 'button');
$text = esc_html($atts['text']);
$url = esc_url($atts['url']);
$color = esc_attr($atts['color']);
return '<a href="/ja/' . $url . '/" style="background:' . $color . ';padding:8px 18px;color:#fff;border-radius:4px;text-decoration:none">' .$text .'</a>';
});
テーマかプラグインか?決定サポートと移行
ショートコードを テーマ レイアウトに影響する場合はプラグインで、テーマとは関係なく使い続けたい場合はプラグインで。こうすることで、テーマを変更しても機能が失われることがなく、アーキテクチャを明確に保つことができる。ドキュメントのために、私は編集者が正しい構文をすぐに見つけられるように、パラメータを含むすべてのショートコードの概要を作成している。後で移動するときは、ショートコードのファイルをエクスポートし、慎重にrequireパスを置き換えます。次の表はその判断の助けになる。
| 用途 | テーマ | プラグイン |
|---|---|---|
| レイアウトへのバインディング | 高い (例:ヒーローボックス) | 低い |
| 移住リスク | テーマ変更でより高く | 低いを保持する。 |
| メンテナンス/アップデート | テーマリリース | より柔軟な自社リリース |
| 対象者 | レイアウトの特徴 | 内容/機能 |
エディターとブロックエディターでショートコードを使う
私は、クラシックエディターでショートコードを直接、次のように追加している。 テキスト をクリックし、ブロックエディターでショートコードブロックを使用します。このように分けることで、コンテンツが明確になり、コピー時のエラーが減ります。エディターに対しては、バックエンドで直接、例えばサンプルブロックやテンプレート内のノートとして例を文書化します。エディター間のスペーシングやインラインスタイルの違いには注意しています。エディタの選択について考えているのであれば、比較の中にある ブロックエディター vs クラシック 役に立つヒント
パフォーマンス:キャッシュとクリーンなクエリー
計算量の多い部分をキャッシュし、データへのアクセスを制限することで、ショートコードを高速に保ちます。 ローディング時間 を使用します。繰り返し発生する問題には、TransientsやWP Object Cacheを意味のあるキーで使っています。posts_per_pageでクエリを制限し、必須フィールドのみを設定し、高価なCOUNTオペレーションを避ける。画像出力にはwidth/heightとlazy loadingを追加して、ページをより早く表示できるようにしています。動的なコンポーネントについては、コンテンツが変更されたらすぐにキャッシュを削除する。
<?php
add_shortcode('latest-offers', function($atts) {
$key = 'sc_latest_offers_v1';
$html = wp_cache_get($key);
if ($html !== false) {
return $html;
}
$q = new WP_Query([
'post_type' => 'angebot',
'posts_per_page' => 5,
'no_found_rows' => true,
'fields' => 'all',
]);
ob_start();
if ($q->have_posts()) {
echo '<ul class="offers">';
while ($q->have_posts()) { $q->the_post();
echo '<li>' . esc_html(get_the_title()) . '</li>';
}
echo '</ul>';
wp_reset_postdata();
}
$html = ob_get_clean();
wp_cache_set($key, $html, '', 600);
return $html;
});
エラーの原因を素早く見つけ、修正する
を起動させる。 デバッグ-モードで、ショートコードが正しく登録されているか確認してください。多くの場合、白い画面や生テキストは、関数がロードされていないか、returnの代わりにechoが使用されていることを示しています。ログ・エントリーは、予期しないデータ型、不正な属性、エスケープの欠落を明らかにします。テンプレートでは、まず静的テキスト、次にショートコード、そしてパラメータと段階的にテストしていきます。体系的に進めたい場合は ワードプレスのデバッグモード.
子テーマでアップデートセーフに動作
で独自のショートコードを作成しています。 子テーマ 親テーマを変更できない場合、あるいは変更したくない場合。こうすることで、テーマのアップデート中もカスタマイズは保持され、ロードの順序をコントロールすることができます。重要:子テーマを正しく登録し、functions.phpを無駄のないものにし、特定のファイルだけをインクルードする。構造化されたプロジェクトの場合、私はショートコードを/incに分け、インラインコメントで文書化します。コンパクトなガイドは 子テーマの使い方.
スタイリング、セマンティクス、アクセシビリティ
きれい好き エッチエムティーエル とセマンティックタグを使うことで、スクリーンリーダーがコンテンツを正しく認識できるようになります。私は、ボタンが本当にリンクである場合のみrole="button "のタグとして表示し、そうでない場合は本物のボタンを選択します。色のコントラストを高く保ち、キーボード・ユーザーがどこにいるのかはっきりわかるようにフォーカス・スタイルを設定する。インラインスタイルを減らし、デザインを明確なクラスのあるCSSファイルに移す。こうすることで、ショートコードの柔軟性とアクセシビリティを同時に保つことができます。
API統合と外部データの安全な統合
で外部データを取得する。 wp_remote_get そして、APIのタイムアウト時にページがハングアップしないように、それらをキャッシュする。レスポンスのステータスコードをチェックし、JSONを制御された方法で解析し、本当に必要なフィールドだけを許可する。失敗した場合は、無駄のないフォールバック出力を表示するか、ブロックを非表示にします。ユーザーコンテンツについては、危険なタグを削除し、リンクを徹底的に検証します。これにより、外部サービスが変動しても、ショートコードの安定性を保つことができる。
使用時のみアセットをロードする
ショートコードのCSS/JSは、実際にページに表示される場合のみ読み込むようにしています。これによりリクエストを節約し、クリティカルパスのCSSを小さく保つことができる。私はスタイルとスクリプトを一元的に登録し、コンテンツ内でショートコードを認識したらすぐにコールバックで、または特別にそれらをエンキューします。重要: 何も考えずにヘッダーにハードコードを書くのではなく、enqueue APIを使って作業しましょう。
<?php // functions.php – アセットの登録 add_action('wp_enqueue_scripts', function() { wp_register_style('my-shortcodes', get_template_directory_uri() . '/assets/shortcodes.css', [], '1.0');
wp_register_script('my-shortcodes', get_template_directory_uri() . '/assets/shortcodes.js', [], '1.0', true); });
// コンテンツに存在する場合にのみロード add_action('wp', function() { if (is_singular() && has_shortcode(get_post_field('post_content', get_queried_object_id()), 'button')) { wp_enqueue_style('my-shortcodes');
wp_enqueue_script('my-shortcodes'); } }); // あるいは、ショートコードコールバックで直接呼び出す: function my_assets_example_shortcode($atts, $content = null) { wp_enqueue_style('my-shortcodes'); return '<div class="my-box">' . wp_kses_post($content) .'</div>';
}
add_shortcode('my-box', 'my_assets_example_shortcode');
ショートコードとテンプレート内の直接関数呼び出しの比較
私は意識的に区別している:固定テンプレートモジュールの場合、ショートコードを解析するのではなく、関数を直接呼び出すことを好む。これにより、オーバーヘッドを節約し、可読性を高め、驚くようなフィルター効果を避けることができる。ショートコードは編集コンテンツ向けであり、テンプレートは明確なパラメータを持つ明確な関数呼び出しから恩恵を受ける。
<?php
// 代わりに
echo do_shortcode('[greeting]');
// テンプレートでは
echo my_greeting_shortcode();
ネストされたショートコードとフォーマット
ネストされたショートコードと、pタグとbrタグの自動挿入を考慮しています。ショートコードが他のコンテンツを囲んでいる場合、do_shortcodeで内部のコンテンツのレンダリングを続けますが、許可されたタグのみを許可します。そうしないとマークアップが破られてしまう場合は、shortcode_unautopでショートコードの周りの見苦しいpタグを削除します。
<?php function my_wrap_shortcode($atts, $content = null) { $inner = do_shortcode($content); // ネストされたショートコードを許可 return '<div class="wrap">' . wp_kses_post($inner) .'</div>';
}
add_shortcode('wrap', 'my_wrap_shortcode');
// オプションの書式設定ヘルプ
add_filter('the_content', 'shortcode_unautop');
国際化とローカリゼーション
私はショートコードを多言語対応にしています:テキスト文字列はテーマのテキストドメインで翻訳し、日付にはdate_i18nを使用しています。この方法で、モジュールは多言語環境で動作し、言語を切り替えても一貫性が保たれます。ショートコードのコールバックでデフォルトテキストを直接ローカライズし、文脈に応じてエスケープします。
<?php
// 翻訳用のテーマを準備する
add_action('after_setup_theme', function() { )
load_theme_textdomain('my-theme', get_template_directory() .'/languages');
});
// 地域化された挨拶
関数 my_greeting_shortcode() {
return esc_html__('Hello, welcome to my website!', 'my-theme');
}
// 地域化された年
add_shortcode('current-year', function() { )
return esc_html(date_i18n('Y'));
});
キャッシュの無効化、バリアントとキー
私は、バリアントがきれいに分離され、変更が加えられたときにコンテンツが速やかに古くなるようにキャッシュを計画する。リミットやタクソノミーのような属性はキーに含まれます。関連する投稿タイプを保存するときは、影響を受けるキーを明確に削除します。トラフィックの多いセットアップでは、永続的なオブジェクトキャッシュバックエンドに頼り、機能ごとにキーをグループ化し、まとめて空にできるようにしている。
<?php
add_shortcode('latest-offers', function($atts) {
$atts = shortcode_atts(['limit' => 5], $atts, 'latest-offers');
$limit = max(1, (int) $atts['limit']);
$key = 'sc_latest_offers_v1_' . $limit;
if (($html = wp_cache_get($key, 'mytheme')) !== false) {
return $html;
}
$q = new WP_Query([
'post_type' => 'angebot',
'posts_per_page' => $limit,
'no_found_rows' => true,
]);
ob_start();
if ($q->have_posts()) {
echo '<ul class="offers">';
while ($q->have_posts()) { $q->the_post();
echo '<li>' . esc_html(get_the_title()) . '</li>';
}
echo '</ul>';
wp_reset_postdata();
}
$html = ob_get_clean();
wp_cache_set($key, $html, 'mytheme', 600);
return $html;
});
// Cache invalidieren, wenn Angebote geändert werden
add_action('save_post_angebot', function() {
foreach ([1,5,10] as $limit) {
wp_cache_delete('sc_latest_offers_v1_' . $limit, 'mytheme');
}
});
セキュリティの強化:サニタイザー、許可属性、rel/target
私はショートコードを、賢明で安全なオプションで拡張している。リンクについては、ターゲットを_self/_blankに限定し、新しいタブにはrel="noopener noreferrer "を設定しています。sanitize_hex_colorで色をチェックしています。コンテンツは文脈を考慮して扱い、囲まれたコンテンツにはwp_kses_postか、より制限の厳しいallowlistを選びます。
<?php
add_shortcode('button', function($atts, $content = null) {
$atts = shortcode_atts([
'text' => '',
'url' => '#'、
'color' => '#2d89ef'、
'target' => '_self'、
], $atts, 'button');
$text = $atts['text'] !== '' ?$atts['text'] : ($content ?: esc_html__('Click now', 'my-theme'));
$text = esc_html($text);
$url = esc_url($atts['url']);
$color = sanitise_hex_color($atts['color']) ?: '#2d89ef';
$target = in_array($atts['target'], ['_self','_blank'], true) ?$atts['target'] : '_self';
$rel = $target === '_blank' ?'noopener noreferrer' : '';
$style = 'background:' .$colour .';padding:8px 18px;color:#fff;border-radius:4px;text-decoration:none';
return '<a class="sc-button" href="/ja/' . $url . '/" style="' . esc_attr($style) . '" target="' . esc_attr($target) . '" rel="' . esc_attr($rel) . '">' .$text .'</a>';
});
エディタ、ウィジェット、フィードコンテキスト
私はショートコードが実行されるコンテキストを考慮します。クラシックなテキストウィジェットではショートコードを明示的に許可し、ブロックウィジェットエディタではショートコードブロックを使用します。フィードや検索では、特に複雑なショートコードを非アクティブにし、空文字列を返します。さらに、ショートコードがコンテンツに表示される場合のみ、単独のページでアセットを読み込むようにしています。
<?php
// クラシックウィジェット: ショートコードを有効にする
add_filter('widget_text', 'do_shortcode');
// フィードでの高価な出力を避ける
add_shortcode('latest-offers-feed-safe', function($atts) { )
if (is_feed()){
return '';
}
// ...正規出力
});
非推奨、ブロックへの移行、互換性
私は自分のショートコードの将来を計画している:タグが置き換えられたら、しばらくの間新しいものにリダイレクトし、変更ログで変更をアナウンスします。ブロックエディタに依存している場合は、サーバーサイドのブロックをrender_callbackで登録し、ショートコードと同じPHP関数を内部で使用することができます。この方法では、ショートコードの有効期限が切れるまで、両方のパスがきれいに共存します。
'', 'url' => '#'], $atts, 'old-button');
$text = $map['text'] ?: $content;
return do_shortcode('[button text="' . esc_attr($text) .'" url="' . esc_url($map['url']) .'"]');
});
// 後で:完全に削除する
// remove_shortcode('old-button');
テストと品質保証
リファクタリングで驚くことがないように、ユニットテストで重要なショートコードを検証しています。テストでは、必須属性がバリデートされていること、デフォルト値が設定されていること、出力が正しくエスケープされていることを確認します。HTML出力については、堅牢なアサーション(完全一致ではなくcontains)を選択し、小さなフォーマットの変更ですべてのテストが壊れないようにしています。また、空のコンテンツ、無効な色、非常に長いテキストなどのエッジケースもテストします。
assertStringContainsString('Hi', $out);
$this->assertStringContainsString('href="#"', $out);
}
public function test_button_blocked_invalid_color() { $out = do_button_blocked_invalid_color()
$out = do_shortcode('[button color="javascript:alert(1)"]');
$this->assertStringNotContainsString('javascript:', $out);
}
}
最後に:私のコンパクトな実践的概要
私は、ショートコードを明確に登録し、安全に配信し、それを キャッシング 素早く。編集用には、例を文書化し、誰もが安心して使えるように一貫したパラメータを確保します。レイアウト関連のモジュールはテーマで、コンテンツ関連の機能はプラグインで、サイトが長期的に柔軟性を保てるようにしています。子テーマ、デバッグログ、クリーンなセマンティクスにより、開発とメンテナンスはリラックスしたままです。その結果、確実にレンダリングされ、メンテナンスが簡単で、コンテンツチームに真の自由を与えるワードプレスのショートコードテーマが完成しました。


