- 結論
- 原因・仕組み
- 手順(サンプルコード)
- 動作確認(検証環境と結果)
- get_template_directory_uri と get_stylesheet_directory_uri の違いの注意点
- get_template_directory_uri と get_stylesheet_directory_uri の違いでよくあるミス
- get_template_directory_uri と get_stylesheet_directory_uri の違いのチェックリスト
- get_template_directory_uri と get_stylesheet_directory_uri の違いのFAQ(よくある質問)
- 筆者の見解(get_template_directory_uri と get_stylesheet_directory_uri の違い)
- get_template_directory_uri と get_stylesheet_directory_uri の違いの関連項目
- 出典(一次情報)
結論
子テーマを使っているサイトで、URL を取得する関数を間違えると、「画像が出ない」「CSS が 404」になります。使い分けは次のとおりです。
| 関数 | 返すもの | 子テーマ使用時 |
|---|---|---|
get_template_directory_uri() |
親テーマ(template)の URL | 常に親テーマ |
get_stylesheet_directory_uri() |
有効なテーマ(stylesheet)の URL | 子テーマ |
get_theme_file_uri( $file ) |
子テーマにファイルがあれば子、無ければ親の URL | 子 → 親の順に探す |
迷ったら、get_theme_file_uri() と get_theme_file_path() を使います。子テーマで上書きされたファイルも、自動で正しい側を指します。親テーマ側のファイルを必ず指したいとき(親の style.css を読み込む等)だけ、get_template_directory_uri() を使います。
原因・仕組み
WordPress のテーマには、template(親テーマのディレクトリ名)と stylesheet(有効なテーマのディレクトリ名)の2つの設定があります。親テーマ単体で使っている場合は同じ値、子テーマを有効にしている場合は異なる値になります。get_template_directory_uri() は前者、get_stylesheet_directory_uri() は後者を基準にします。公式リファレンスにも、子テーマの URL が欲しいときは get_stylesheet_directory_uri() を使う旨と、末尾にスラッシュが付かない旨が記載されています。また、get_theme_file_uri() は 4.7.0 で追加され、子テーマと親テーマを考慮して URL を返します。
手順(サンプルコード)
add_action( 'wp_enqueue_scripts', function () {
// 親テーマの CSS(親の style.css を読む)
wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css', array(), null );
// 子テーマの CSS(子の style.css)
wp_enqueue_style( 'child-style', get_stylesheet_directory_uri() . '/style.css', array( 'parent-style' ), null );
// 子で上書きできる画像・JS はこちらが安全
wp_enqueue_script( 'ks-app', get_theme_file_uri( 'js/app.js' ), array(), '1.0', true );
} );
// テンプレート内の画像
printf( '<img src="%s" alt="">', esc_url( get_theme_file_uri( 'images/logo.png' ) ) );
パス(include 用)は、URL とは別の関数です。get_template_directory()、get_stylesheet_directory()、get_theme_file_path() を、同じ考え方で使い分けます。URL をファイル読み込み(include)に使ってはいけません。
動作確認(検証環境と結果)
WordPress 7.1.2、PHP 8.2.12 で、DB を変更せず、pre_option_template / pre_option_stylesheet フィルターで「親 = twentytwentyfive、子 = ks-child」を擬似的に再現しました(php C:Tempwp-testrun.php template-directory-uri-vs-stylesheet-directory-uri.php)。
get_template_directory_uri():http://localhost/wp-content/themes/twentytwentyfiveget_stylesheet_directory_uri():http://localhost/wp-content/themes/ks-childget_template_directory()とget_stylesheet_directory()は、同様に親・子のディレクトリを返した。- 子テーマのディレクトリが実在しない状態で
get_theme_file_uri( 'assets/a.css' )を呼ぶと、親テーマ側の URL を返した(子に無ければ親へフォールバック)。
続いて、pre_option_home を https://example.com、pre_option_siteurl を https://example.com/wp にして比較しました。
| 関数 | 結果 |
|---|---|
home_url( '/about/' ) |
https://example.com/about/ |
site_url( '/wp-login.php' ) |
http://example.com/wp/wp-login.php |
admin_url() |
http://example.com/wp/wp-admin/ |
wp_login_url() |
http://example.com/wp/wp-login.php |
site_url() 系で http になったのは、CLI 実行で is_ssl() が false のためです。wp-includes/link-template.php を読むと、get_site_url() はスキーム未指定のとき set_url_scheme() で is_ssl() に合わせる一方、get_home_url() は is_ssl() が false なら保存値のスキームを使う実装でした(検証環境 7.1.2 のソースで確認)。実際のサイトでは、設定の「WordPress アドレス」と「サイトアドレス」の両方を https で保存し、https でアクセスしてください。
プラグインの URL は、plugins_url( 'assets/app.js', WP_PLUGIN_DIR . '/ks-demo/ks-demo.php' ) が http://localhost/wp-content/plugins/ks-demo/assets/app.js、plugin_dir_url() が .../plugins/ks-demo/(末尾スラッシュ付き)を返しました。引数なしの plugins_url() は .../wp-content/plugins です。
get_template_directory_uri と get_stylesheet_directory_uri の違いの注意点
home_url()はサイトの公開 URL(訪問者がアクセスする場所)、site_url()は WordPress のコアファイルがある場所です。WordPress を/wpのサブディレクトリに置く構成では、両者が異なります。- URL を出力するときは
esc_url()、属性やテキストには別のエスケープ関数を使います。 - テーマ名のディレクトリを
/wp-content/themes/と直書きしないでください。WP_CONTENT_URLの変更や、ディレクトリ移動で壊れます。 - プラグインの中では、
__FILE__を渡すplugins_url()かplugin_dir_url( __FILE__ )を使うのが一般的です。 - 親テーマのアップデートで、親側のファイルは上書きされます。子テーマ側に置いたファイルは残ります。
get_template_directory_uri と get_stylesheet_directory_uri の違いでよくあるミス
- 子テーマで
get_template_directory_uri()を使い、子テーマに置いた画像が表示されない。 - URL と同じつもりで、
include get_template_directory_uri() . '/x.php';と書く。 home_url()の戻り値に、さらに/を付けて二重スラッシュになる。パスを渡す形(home_url( '/about/' ))を使う。- テーマ内で、
http://から始まる絶対 URL を直書きして、https 化で混在コンテンツになる。 - 子テーマの
style.cssを、親のstyle.cssの読み込み後に出さない。
get_template_directory_uri と get_stylesheet_directory_uri の違いのチェックリスト
- 子テーマを使っているか確認したか。
- 子で上書きする可能性があるファイルに、
get_theme_file_uri()を使ったか。 includeには、URL ではなくパスの関数を使ったか。- 出力に
esc_url()を使ったか。 - https 化後、WordPress アドレスとサイトアドレスの両方を確認したか。
get_template_directory_uri と get_stylesheet_directory_uri の違いのFAQ(よくある質問)
Q. 親テーマ単体のとき、どれを使っても同じですか。
A. 同じ結果になります。ただし、将来の子テーマ化に備えて、get_theme_file_uri() を使っておくと安全です。
Q. get_home_url と home_url の違いは?
A. home_url() は現在のサイトの get_home_url() を呼ぶ短縮形です。マルチサイトで別サイトの URL が欲しいときは get_home_url( $blog_id ) を使います(get_home_url() の使い方|説明・引数・注意点)。
Q. プラグインの CSS の URL は?
A. plugins_url( 'css/style.css', __FILE__ ) です(plugins_url() の使い方|説明・引数・注意点)。
筆者の見解(get_template_directory_uri と get_stylesheet_directory_uri の違い)
URL 関数の使い分けは、基準を1つ決めるだけで迷いが減ると考えます。私見では、テーマ内のアセットは原則として get_theme_file_uri()、親テーマを明示的に指す場合だけ get_template_directory_uri()、とルール化するのがよいです。さらに、サイトの URL は直書きせず、必ず関数から取得する習慣が、移設や https 化のときの手戻りを減らします。
get_template_directory_uri と get_stylesheet_directory_uri の違いの関連項目
- get_template_directory_uri() の使い方|説明・引数・注意点
- get_stylesheet_directory_uri() の使い方|説明・引数・注意点
- get_theme_file_uri() の使い方|説明・引数・注意点
- home_url() の使い方|説明・引数・注意点
- site_url() の使い方|説明・引数・注意点
