投稿本文のサイトアドレス置換ショートコード
2025.03.27
WordPressを使用したサイトで投稿の本文(固定ページも同様)にサイト内の別ページのリンクを記述するときのお話です。
【WordPressのサイトアドレス (URL)が http(s)://www.example.com の場合】
ブロックエディターを使用するにしろ、クラシックエディタを使用するにしろ、通常はリンク部分のURLや表示したいURLとして「http(s)://www.example.com/sample_page/」のような文字列が投稿本文には登録されます。これは投稿本文内に画像を表示させる際も同様で画像を表示するために「http(s)://www.example.com/wordpress/wp-content/uploads/2025/03/xxxx.jpg」のようなhtmlのコードがたくさん記述(登録)されることとなります。
永遠にドメインの変更はしないと誓って(?)サイト運営されている場合は特に問題はないかもしれませんが、何らかの事情でWordPressのドメインの変更サイトアドレス (URL)を変更しなくてはならない場合、投稿本文内に登録されている変更前のURLは変更後は正しいURLではなくなるため大きな問題になります。
(例えば http(s)://www.example.com を http(s)://www.sample.com に変更しなければならない場合等)
WebサイトをSSL化する際も同様のことが言えますが、SSL化の場合は.htaccessでリダイレクト設定を行うだけでも当面は問題にならないかもしれません。
また、WordPressを使用したサイトの制作を請け負う企業・事業者の方は本サーバーで制作する前にテスト環境、ステージング環境等で事前にサイトを一通り仕上げた後、本番環境へデータを移行するようなケースも多いように思います。この際にもテスト環境と本番環境で違うドメイン設定のWordPress間でのデータの移行(投稿データを含む)が必要になるケースがあります。
インターネットで「WordPress ドメイン変更」などと検索するとこういった場合の解決方法がいくつも出てきますが、大きな選択肢としては『プラグインなどを使用して変更する』『手順を確認しながら手作業で変更する』『専門の業者さんにお願いする』といったものになるかと思います。どの方法を選択しても良いかと思いますが、間違いなく的確に行う必要があるという点を念頭に選択しましょう。
この問題の解決方法としてネット検索して出てくるサイトの情報がすべて正しい(的確な)手法ではないということは知っておいた方が良いかもしれません。
※すべてのサイトを確認はしていませんが、もしかすると『WordPressの公式ドキュメントでは◯◯◯はやらないでください』と掲載されていることを当然のように行うよう記載しているサイトも多いかもしれません。
前置きが長くなりましたが、私はWordPressでサイトを制作する際、functions.phpに下記のような記述を行い、投稿データの内容でよく使用されるURLや電話番号等で変更される可能性があるものはショートコードとして保存されるようにしておきます。
変更される可能性があるURLやワード、一括して登録、変更できたら便利な電話番号や住所などを事前にショートコードとして登録しておき、WordPressのデータベースへ保存される文字列はショートコードとして保存しておくという仕組みです。
下記のようなコードをfunctions.phpなどに記述するとデータベース内、例えば wp_posts テーブルの post_content に保存されるデータはサイトアドレス (URL) http(s)://www.example.com ではなく [home_url] という文字列ですべて登録されます。他の [theme_dir] 、 [my_tel] 、 [my_address] も同様です。
サイト制作時にこうしたことを将来起こりうることとして認識していれば、多くのサイトで掲載されているようなデータベースのバックアップファイル(ダンプファイル)のURLを一括して置換するといった作業はほとんどの場合、不要になります。特に上記の参考サイトにもある通りGUIDは本来、置換(変更)するべきものではありません。
// Set shortcode configuration
$_MY_SHORTCODE = [
// Note: When saving the post, the replacements will be made in order from top to bottom. Do not override when registering shortcodes.
// 設定サンプル: ['[ショートコードの名前]', '出力する関数、あるいは値', '出力された値に適用するコールバック関数1(省略可)', 'コールバック関数2(省略可)', ...],
['[home_url]', 'home_url', 'esc_url'], // esc_url(home_url()) をショートコード [home_url] として登録
['[theme_dir]', 'get_stylesheet_directory_uri', 'esc_url'], // esc_url(get_stylesheet_directory_uri()) をショートコード [theme_dir] として登録
['[my_tel]', '[my_tel]', 'esc_attr'], // esc_attr('[my_tel]') をショートコード [my_tel] として登録 電話番号変更時はここを変更すると表示される番号が変わる
['[my_address]', '東京都東神田1-1-1'], // '東京都東神田1-1-1' をショートコード [my_address] として登録 住所変更時はここを変更すると表示される住所が変わる
];
define('MY_SHORTCODE', $_MY_SHORTCODE);
/**
* This function is used to replace the shortcode with a string on the edit page. An action hook of edit_form_top.
* This action hook is set with set_my_short_code().
* Array constant 'MY_SHORTCODE' required.
* Note: When you save a post, it will be replaced in the order of registration.
* @param WP_Post $post Post object.
* @return void
*/
function relpace_shortcode_admin($post)
{
$shortcode = MY_SHORTCODE;
$post_type = [
// ショートコードを適用したい投稿タイプを配列で指定
'post',
'page',
];
if (in_array($post->post_type, $post_type)) {
$needle = [];
$replace = [];
foreach ($shortcode as $val) {
if (count($val) < 2) {
continue;
}
$shortcode_tag = str_replace(['[', ']'], '', $val[0]);
if (!empty($shortcode_tag) && shortcode_exists($shortcode_tag)) {
$exec_shortcode = $val[0];
$needle[] = $exec_shortcode;
$replace[] = do_shortcode($exec_shortcode);
$post->post_content = str_replace($needle, $replace, $post->post_content);
}
}
}
}
/**
* This function is used to replace the replaced shortcode string with the shortcode when the edit page is saved.
* An action hook of save_post. This action hook is set with set_my_short_code().
* Array constant 'MY_SHORTCODE' required.
* Note: When you save a post, it will be replaced in the order of registration.
* @param integer $post_id Post ID.
* @param WP_Post $post Post object.
* @param boolean $update Whether this is an existing post being updated.
* @return void
*/
function save_shortcode_admin($post_id, $post, $update)
{
$shortcode = MY_SHORTCODE;
$post_type = [
// ショートコードを適用したい投稿タイプを配列で指定
'post',
'page',
];
if (in_array($post->post_type, $post_type)) {
$needle = [];
$replace = [];
foreach ($shortcode as $val) {
if (count($val) < 2) {
continue;
}
$shortcode_tag = str_replace(['[', ']'], '', $val[0]);
if (!empty($shortcode_tag) && shortcode_exists($shortcode_tag)) {
$exec_shortcode = $val[0];
$needle[] = $exec_shortcode;
$replace[] = do_shortcode($exec_shortcode);
}
}
$my_post = [
'ID' => $post_id,
'post_title' => $post->post_title,
'post_content' => str_replace($replace, $needle, $post->post_content),
];
remove_action('save_post', 'save_shortcode_admin', 13, 3);
wp_update_post($my_post);
add_action('save_post', 'save_shortcode_admin', 13, 3);
}
}
/**
* This function is used to register a simple shortcode to replace the text. Array constant 'MY_SHORTCODE' required.
* Note: This method does not override when registering shortcodes.
* @param void
* @return void
*/
function set_my_short_code()
{
if (!defined('MY_SHORTCODE') || !is_array(MY_SHORTCODE) || empty(MY_SHORTCODE)) {
return;
}
$shortcode = MY_SHORTCODE;
foreach ($shortcode as $val) {
if (count($val) < 2) {
continue;
}
$shortcode_tag = str_replace(['[', ']'], '', $val[0]);
if (!empty($shortcode_tag) && $shortcode_tag !== $val[0] && !shortcode_exists($shortcode_tag)) {
add_shortcode($shortcode_tag, function () use($val) {
$result = '';
for ($i = 1; $i < count($val); $i++) {
if (function_exists($val[$i])) {
$result = call_user_func($val[$i], $result);
} else {
$result = $val[$i];
}
}
return $result;
});
}
}
add_action('edit_form_top', 'relpace_shortcode_admin');
add_action('save_post', 'save_shortcode_admin', 13, 3);
// 2025.08.05 追記 ブロックエディターにも適用 追記したfunctionを記述した上で下記を追加
add_filter('rest_post_dispatch', 'rest_response_post_filter', 10, 3);
add_filter('my_rest_post_content_filter', 'relpace_shortcode_admin_rest', 10, 3);
}
// Set shortcode
set_my_short_code();
1行目から10行目の部分はショートコードの設定部分です。$_MY_SHORTCODE配列の要素として設定したいショートコードを配列の形で設定します。
要素となる配列の設定の仕方は4行目の通りです。コールバックは複数設定可能ですが不要であれば省略も可能です。' [ショートコードの名前] ' と ' 出力する関数、あるいは値 ' は必須です。
定数やグローバルな変数あまり使用したくない場合は新たなclassを作成し、その中で上記コードを適用しても(書き換えても)良いかと思います。(その方が良いでしょう。)
12行目から122行目までは特に変更の必要なないかと思いますが、上記の例では投稿タイプは post と page を対象にショートコードの置換を行っています。その他に適用したい投稿タイプ、あるいは page には適用したくない等があれば、23〜27行目、59〜63行目の配列に投稿タイプを追加、削除してください。
※Contact Form 7などのようにこの部分への追加ではなく、wpcf7_add_form_tag()を使用してショートコードを追加する必要があるカスタム投稿タイプもありますが、考え方・設定方法は同様です。
125行目でset_my_short_code()を実行し、'edit_form_top'と'save_post'のhookを登録します。
※どのような状態でデータベースに登録されているかは120行目をコメントアウトすると管理画面の投稿ページではショートコードを変換せずに表示しますので確認可能です。
※ブロックエディターをご利用の場合は120行目は実行されない状態となりますので、ブロックエディタに表示される(保存される)コードは下記のような記述となります。
※ブロックエディターにも適用されるようにするhookを追記しました。
<!-- wp:shortcode -->
[home_url]/wp/wp-content/uploads/2025/03/ca49f15f9b95aa9a7284dae2aacb195b.jpg
<!-- /wp:shortcode -->
このコードはすでに稼働しているサイトに適用することも可能です。登録済みの投稿データはショートコードではなく生の文字列(サイトアドレスや電話番号等)でデータが保存されていますが、それらの過去の投稿データを投稿画面で更新するとショートコードに該当する文字列はショートコードに置き換えられてデータベースに保存されます。一手間かかりますが、投稿数がそれほど多くない場合は後から適用することも後々のことを考えるとアリかもしれません。
追記 2025.08.05
ブロックエディターにもショートコードを適用されるようにするには下記を追加します。
ブロックエディターはRest API経由でデータを読み込むため、Rest API経由のWP_Postにフィルターフックを作り、ショートコードの置換を適用します。
/**
* This function is used to add hooks for the block editor for the Rest API.
* @param WP_Rest_Response $result Result to send to the client. Usually a WP_REST_Response.
* @param WP_REST_Server $server Server instance.
* @param WP_REST_Request $request Request used to generate the response.
* @return WP_Rest_Response
*/
function rest_response_post_filter(WP_Rest_Response $result, WP_REST_Server $server, WP_REST_Request $request)
{
$custom_post = $this->custom_post;
$custom_post_type = array_keys($custom_post);
$data = $result->get_data();
if (!$data || !is_array($data) || !isset($data['content']) || !isset($data['type']) || !isset($data['id'])) {
return $result;
}
$data['content'] = apply_filters('my_rest_post_content_filter', $data['content'], $data, $result);
$result->set_data($data);
return $result;
}
/**
* This function is used to replace the replaced shortcode string with the shortcode with block editor.
* @param array $content The content data of Rest API.
* @param array $data Response data of Rest API.
* @param WP_Rest_Response $result Result to send to the client. Usually a WP_REST_Response.
* @return array
*/
function relpace_shortcode_admin_rest(array $content, array $data, WP_Rest_Response $object)
{
$shortcode = MY_SHORTCODE;
$post_type = $data['type'] ?? '';
$post_id = $data['id'] ?? 0;
if ($post_type === 'post' || $post_type === 'page') {
$needle = [];
$replace = [];
foreach ($shortcode as $val) {
if (count($val) < 2) {
continue;
}
$shortcode_tag = str_replace(['[', ']', '*'], '', $val[0]);
if (!empty($shortcode_tag) && shortcode_exists($shortcode_tag)) {
$exec_shortcode = $val[0];
$needle[] = $exec_shortcode;
$replace[] = do_shortcode($exec_shortcode);
$content['raw'] = str_replace($needle, $replace, $content['raw']);
}
}
}
return $content;
}