WordPress Logo WordPress テンプレート関係の関数

更新日:2019年07月23日

作成日:2019年02月07日

テンプレートの読み込みを行う関数

WordPress では、投稿などのデータベースに格納されたデータをテンプレート(ページの雛形)を使って表示します。

一般的な Web サイトの構造は、ヘッダー、コンテンツ部分、サイドバー、フッターなどから構成されています。WordPress でサイトを作成する際にページごとにテンプレートを作成していくと、ヘッダーやフッターなどの共通部分を繰り返し記述することになってしまいます。

このため、共通の部分(パーツ)は header.php、content.php、sidebar.php、footer.php などの「テンプレートパーツ」と呼ばれるテンプレートファイルに記述して、各テンプレートでそれぞれのテンプレートパーツを読み込むようにします。

テンプレートパーツを読み込む関数を「インクルードタグ」と呼びます。また、テンプレートパーツは「パーツテンプレート」や「モジュールテンプレート」と呼ばれることもあります。

インクルードタグは wp-includes/general-template.php で定義されています。

テンプレートパーツ

WordPress では、ページのテンプレートを以下のようなテンプレートパーツに分割して管理します。

  • ヘッダー:header.php
  • コンテンツ部分:content.php
  • サイドバー:sidebar.php
  • フッター:footer.php

以下は、テンプレートパーツによる分割の概念図です。

テンプレートパーツによる分割の概念図

以下は、テンプレートパーツの読み込みの概念図です。

テンプレートパーツの読み込みの概念図

テンプレートパーツ(テンプレートファイル)とそのインクルードタグ
パーツ ファイル名 読み込むためのインクルードタグ
ヘッダー header.php <?php get_header(); ?>
header-{name}.php(※1) <?php get_header($name); ?>
フッター footer.php <?php get_footer(); ?>
footer-{name}.php(※1) <?php get_footer($name); ?>
サイドバー sidebar.php <?php get_sidebar(); ?>
sidebar-{name}.php(※1) <?php get_sidebar($name); ?>
検索フォーム searchform.php <?php get_search_form(); ?>
コメント comments.php <?php comments_template(); ?>
カスタム aaa.php(※2) <?php get_template_part('aaa'); ?>
aaa-bbb.php(※2) <?php get_template_part('aaa', 'bbb'); ?>

(※1)ヘッダー、フッター、サイドバーのテンプレートパーツで名前(name)を指定すると、指定したテンプレートパーツ header-{name}.php(ヘッダーの場合) を読み込みます。

(※2)任意のテンプレートパーツを読み込む場合は、get_template_part() を使用します。

以下はインクルードタグを使ったテンプレートの例です(_s テーマの index.php から引用) 。

2行目、20行目、25行目、及び32、33行目でインクルードタグが使われています。

<?php
get_header();  //header.php の読み込み
?>
<div id="primary" class="content-area">
  <main id="main" class="site-main">
    <?php
    if ( have_posts() ):
      if ( is_home() && !is_front_page() ):
        ?>
    <header>
      <h1 class="page-title screen-reader-text">
        <?php single_post_title(); ?>
      </h1>
    </header>
    <?php
      endif;
      while ( have_posts() ):
        the_post();
        //template-parts フォルダ内の content-xxxx.php の読み込み
        //xxxx は get_post_type の値
        get_template_part( 'template-parts/content', get_post_type() );
      endwhile;
        the_posts_navigation();
    else :
      //template-parts フォルダ内の content.php の読み込み
      get_template_part( 'template-parts/content' );
    endif;
    ?>
  </main>
  <!-- #main -->
</div> <!-- #primary -->
<?php
get_sidebar();  //sidebar.php の読み込み
get_footer();  //footer.php の読み込み

以下はインクルードタグの1つ get_header() のソースです。

function get_header( $name = null ) {
  /**
   * Fires before the header template file is loaded.
   *
   * @since 2.1.0
   * @since 2.8.0 $name parameter added.
   *
   * @param string|null $name Name of the specific header file to use. null for the default header.
   */
  do_action( 'get_header', $name );

  $templates = array();
  $name = (string) $name;
  if ( '' !== $name ) {
    $templates[] = "header-{$name}.php";
  }

  $templates[] = 'header.php';

  locate_template( $templates, true );
}

最初に get_header アクション フックが実行されています。そして $name が指定されていれば header-{$name}.php を変数 $templates(配列)に追加し、その後 header.php を追加しています。

最後に、locate_template() を使って変数 $templates に入っている名前のファイルを読み込んでいます。locate_template() は指定された名前のファイルを探して読み込む関数です。

現在のテーマのディレクトリに header.php がなければ、wp-includes/theme-compat/ の中を探します。wp-includes/theme-compat/ の中には、デフォルトテーマの header.php、footer.php、sidebar.php などが入っているので、この header.php が読み込まれることになります。

以下はテンプレートの読み込みを行う関数やそれに関連する関数です。

get_header

テーマのヘッダー(header.php テンプレートファイル)を読み込みます。名前(name)を指定すると、指定したヘッダー header-{name}.php を読み込みます。

header.php または header-{name}.php がテーマに含まれていない場合は、デフォルトテーマの wp-includes/theme-compat/header.php を読み込みます。

get_header( $name )

パラメータ
$name(文字列):(オプション)指定した場合は header-name.php($name が name の場合)を読み込みます。
戻り値
なし

複数のヘッダー(テンプレートパーツ)の使い分け

ヘッダー部分を複数用意し、組み込み先のテンプレートに応じてヘッダー部分を切り替えることができます。

  • テーマ内に「header-xxxx.php」のような名前のヘッダーテンプレートパーツを複数用意
  • 条件分岐タグを使ってテンプレートにより get_header('xxxx') と記述して読み込む

以下の場合、header-home.php と header-404.php を用意しておき、

  • ホームの場合は header-home.php を、
  • 404ページの場合は header-404.php を、
  • その他の場合は header.php
を読み込む例です。

<?php
if ( is_home() ) :  //ホームの場合
  get_header('home');  //header-home.php
elseif ( is_404() ) :  //404ページの場合
  get_header('404');  //header-404.php
else :  //その他の場合
  get_header();  //header.php
endif;
?>

get_sidebar

テーマのサイドバー(sidebar.php テンプレートファイル)を読み込みます。 名前 ($name) を指定すると、対応するサイドバー sidebar-{name}.php を読み込みます。

sidebar.php または sidebar-{name}.php がテーマに含まれていない場合は、デフォルトテーマの wp-includes/theme-compat/sidebar.php からサイドバーを読み込みます。

get_sidebar( $name )

パラメータ
$name(文字列):(オプション)指定した場合は sidebar-name.php($name が name の場合)を読み込みます。
戻り値
なし

左右2つのサイドバーを配置する例

sidebar-right.php と sidebar-left.php を用意して、以下のように読み込みます。

<?php get_header(); ?>
<?php get_sidebar('left'); ?>
<?php get_sidebar('right'); ?>
<?php get_footer(); ?>

複数のサイドバー(テンプレートパーツ)の使い分け

サイドバー部分を複数用意し、組み込み先のテンプレートに応じてサイドバー部分を切り替えることができます。

  • テーマ内に「sidebar-xxxx.php」のような名前のサイドバーテンプレートパーツを複数用意
  • 条件分岐タグを使ってテンプレートにより get_sidebar('xxxx') と記述して読み込む

以下の場合、sidebar-home.php と sidebar-404.php を用意しておき、

  • ホームの場合は sidebar-home.php を、
  • 404ページの場合は sidebar-404.php を、
  • その他の場合は sidebar.php
を読み込む例です。

<?php
if ( is_home() ) :  //ホームの場合
  get_sidebar('home');  //sidebar-home.php
elseif ( is_404() ) :  //404ページの場合
  get_sidebar('404');  //sidebar-404.php
else :  //その他の場合
  get_sidebar();  //sidebar.php
endif;
?>

get_search_form

テーマの searchform.php ファイルを使用して検索フォームを表示します。テーマに searchform.php ファイルがない場合は WordPress に組み込みの検索フォームを表示します。

get_search_form( $echo )

パラメータ
$echo(真偽値):(オプション) true ならフォームを表示します。false なら表示せずフォームを文字列として返します。初期値: true
戻り値
パラメータ $echo が false ならフォームの HTML を返します。

テンプレートに以下を記述すれば、その場所に検索フォームが表示されます。

<?php get_search_form(); ?>

テーマに searchform.php ファイルがない場合は以下のような WordPress デフォルトの検索フォームが読み込まれます。

<!-- HTML4 フォーム -->
<form role="search" method="get" id="searchform" class="searchform" action="<?php echo esc_url( home_url( '/' ) ); ?>">
  <div>
    <label class="screen-reader-text" for="s"><?php _x( 'Search for:', 'label' ); ?></label>
    <input type="text" value="<?php echo get_search_query(); ?>" name="s" id="s" />
    <input type="submit" id="searchsubmit" value="<?php echo esc_attr_x( 'Search', 'submit button' ); ?>" />
  </div>
</form>
          
<!-- HTML5 フォーム -->
<form role="search" method="get" class="search-form" action="<?php echo esc_url( home_url( '/' ) ); ?>">
  <label>
    <span class="screen-reader-text"><?php echo _x( 'Search for:', 'label' ) ?></span>
    <input type="search" class="search-field" placeholder="<?php echo esc_attr_x( 'Search …', 'placeholder' ) ?>" value="<?php echo get_search_query() ?>" name="s" title="<?php echo esc_attr_x( 'Search for:', 'label' ) ?>" />
  </label>
  <input type="submit" class="search-submit" value="<?php echo esc_attr_x( 'Search', 'submit button' ) ?>" />
</form>

HTML5 フォームを表示させるには、以下を functions.php に記述します。

add_theme_support( 'html5', array( 'search-form' ) );
独自の検索フォームの設置

検索フォームをカスタマイズしたい場合は、検索フォームのテンプレートパーツ searchform.php を独自に作成します。

  • 検索キーワードを入力するテキストボックスの name 属性 を s と指定します。(必須)
  • the_search_query() を利用して検索結果ページに検索キーワードを出力します。
  • アクセシビリティのために、form 要素に role 属性(値:search )を指定し、入力するテキストボックスに aria-label 属性でラベルを付けます。

name 属性 を s とすることで submit ボタンをクリックすると get メソッドでテキストボックスに入力された値が検索キーワードとして送信されます。

以下は searchform.php の例です。

<form role="search" method="get" class="search-form" action="<?php echo esc_url( home_url( '/' ) ); ?>">
  <input type="search" class="search-field" placeholder="検索" value="<?php the_search_query(); ?>" name="s" aria-label="このサイトで検索">
  <input type="submit" class="search-submit" value="検索">
</form>

以下は、input 要素の代わりに button 要素とアイコンフォント(Fontawesome のための i 要素を使う例です。この場合、i 要素は単に装飾目的なので aria-hidden="true" を指定しています。

また、前述の例では action 属性の値は home_url()エスケープ処理して出力していますが、この例では空にしています。(form タグの action 属性

<form role="search" method="get" class="search-form" action="">
  <input type="search" class="search-field" placeholder="検索" value="<?php the_search_query(); ?>" name="s" aria-label="このサイトで検索">
  <button type="submit" class="search-submit">
    <i class="fas fa-search" aria-hidden="true"></i> 検索
  </button>
</form>

検索結果に投稿だけを表示

検索結果に投稿だけを(固定ページ等を除外して)表示したい場合は、下記の input 要素をフォームに追加します(type="hidden" を指定しているので表示されません)。

post_type のデフォルト値は any で、投稿・固定ページ・カスタム投稿タイプを意味しますが、以下のように value 属性の値を post とすることで投稿だけを対象にすることができます。

<input type="hidden" value="post" name="post_type" id="post_type" />

get_search_form アクションを使う例

カスタム関数を functions.php に記述して、その関数を get_search_form アクションにフックする方法もあります。以下は例です。この場合、searchform.php が存在していてもこちらの記述が優先されます。

function my_search_form( $form ) {
  $form = '<form role="search" method="get" class="search-form" action="'.esc_url( home_url( '/' ) ).'">
    <input type="search" class="search-field" placeholder="検索" value="'.the_search_query().'" name="s" aria-label="このサイトで検索">
    <input type="submit" class="search-submit" value="検索">
  </form>';
  return $form;
}
add_filter( 'get_search_form', 'my_search_form' );
検索結果の表示

検索結果はテンプレート search.php を使って表示することができます。search.php でループを記述すると、取得された検索結果を出力できるようになっています。

ユーザーが入力した検索キーワードは the_search_query() で出力することができますが、この関数は属性値に出力するようにエスケープ処理されているので、以下のように get_search_query() で取得した値を esc_html() でエスケープして出力しています。

また、以下の例では、検索キーワードに該当する記事がない場合の処理(検索フォームの再表示)も記述してあります。

<?php get_header(); ?>
<div class="contents">
  <div class="search_results">
    <!-- ループ -->
    <?php if(have_posts()): ?>
    <!-- 検索キーワードに該当する記事がある場合の処理 -->
    <!-- 検索キーワードを出力 -->
    <h2>検索結果:「<?php echo esc_html( get_search_query( false ) ); ?>」</h2>
    <?php while(have_posts()): the_post(); ?>
    <!-- 該当する記事のタイトルにリンクを付けて表示 -->
    <?php the_title( '<h3><a href="'.esc_url( get_permalink()).'">', '</a></h3>'); ?>
    <!-- 該当する記事の抜粋を表示 -->
    <div class="excerpt">
      <?php the_excerpt(); ?>
      <p><a href="<?php the_permalink(); ?>">続きを読む</a></p>
    </div><!-- end of .excerpt -->
    <?php endwhile; ?>
    <?php else: ?>
    <!-- 検索キーワードに該当する記事がない場合の処理-->
    <!-- 検索キーワードを出力-->
    <h2>「<?php echo esc_html( get_search_query( false ) ); ?>」の検索結果が見つかりませんでした。</h2>
    <p>別のキーワードでお試しください。</p>
    <!-- 検索フォームを表示-->
    <?php get_search_form(); ?>
    <?php endif;  ?>
  </div><!-- end of .search_results -->
</div> <!-- end of .content -->

the_search_query

検索が行われた時に入力された文字列(検索キーワード)を表示します。この関数は HTML 属性の中で出力する場合は安全です(エスケープ処理は esc_attr() が使用されています)。

the_search_query()

パラメータ
なし
戻り値
なし

検索フォームに入力された検索キーワードを input 要素の value 属性に出力する例です。

<input type="search" value="<?php the_search_query(); ?>" name="s">

HTML に出力する場合は、以下のように get_search_query()esc_html() を使って出力します。

esc_html() と esc_attr() は機能的には同じなので、どちらでも問題はないと思いますが、出力される際に適用されるフィルターが異なります。

<h2>検索結果:「<?php echo esc_html( get_search_query( false ) ); ?>」</h2>

以下がソースです。

get_search_query() で取得した値に the_search_query フィルターを適用し、esc_attr() でエスケープ処理して出力しています。

function the_search_query() {
  /**
   * Filters the contents of the search query variable for display.
   *
   * @since 2.3.0
   *
   * @param mixed $search Contents of the search query variable.
   */
  echo esc_attr( apply_filters( 'the_search_query', get_search_query( false ) ) );
}

get_search_query

検索フォームで入力された検索キーワードを取得します。引数に false を指定して取得した値を出力する場合はエスケープ処理が必要です。

get_search_query( $escaped )

パラメータ
$escaped(真偽値):(オプション) 結果をエスケープするかどうか。デフォルトは true でエスケープします。false を指定した場合は後でエスケープする必要があります。 初期値: true
戻り値
検索フォームでユーザが入力した検索キーワード(文字列)

検索キーワードを出力する例です。

<p>「<?php echo esc_html( get_search_query( false ) ); ?>」の検索結果が見つかりませんでした。</p>

以下がソースです。

get_query_var() で取得した値に get_search_query フィルタを適用して、$escaped が true の場合は esc_attr() でエスケープ処理しています。

function get_search_query( $escaped = true ) {
  /**
    * Filters the contents of the search query variable.
    *
    * @since 2.3.0
    *
    * @param mixed $search Contents of the search query variable.
  */
  $query = apply_filters( 'get_search_query', get_query_var( 's' ) );

  if ( $escaped )
    $query = esc_attr( $query );
  return $query;
}

comments_template

コメントテンプレートを読み込みます。comments.php がテーマに含まれていない場合は、デフォルトテーマの wp-includes/theme-compat/comments.php から読み込みます。

投稿(post)か固定ページ(page)以外のページから呼ばれた場合はコメントは表示されません(single.php または page.php で使用します)。

comments_template( $file, $separate_comments )

パラメータ
  • $file(string):(オプション)読み込むコメントテンプレートファイルを指定します。先頭に「/」を付けて指定します。初期値: /comments.php
  • $separate_comments(boolean):(オプション)タイプによりコメントを分離するかどうかの真偽値。区切る場合は true、区切らない場合は false。初期値: false
戻り値
なし

comments.php 以外のテンプレートを読み込むときは、comments_template() の第1引数にファイル名を指定します。

<?php comments_template('/single_comments.php'); ?>

get_template_part

任意のテンプレートファイルを読み込みます。一致するテンプレートファイルが見つからない場合に警告を出しません。

get_template_part( $slug, $name )

パラメータ
  • $slug(文字列):(必須) テンプレートのスラッグ名
  • $name(文字列):(オプション) 特定テンプレートの名前
戻り値
なし

第一引数(スラッグ名)で、組み込むテンプレートファイルの名前を指定します(拡張子 .php は付けません)。以下は「content.php」というテンプレートを組み込む例です。

<?php get_template_part('content'); ?> 

第二引数(名前)も指定すると、「スラッグ名 - 名前.php」のテンプレートがあればそのファイルを組み込み、なければ「スラッグ名.php」を組み込みます。

以下の場合、「content-page.php」があればそれを組み込み、なければ「content.php」を組み込みます。

<?php get_template_part( 'content', 'page' ); ?>

上記の場合、get_template_part('content-page') と記述しても「content-page.php」を組み込むことはできますが「content-page.php」がない場合に「content.php」を組み込みません。

また、$slug はアクションフック get_template_part_{$slug} で利用できるので(挿入時に割り込み処理ができる単位なので)、テンプレートファイルの種類ごとに slug を分けておくと便利になります。

サブフォルダにファイルがある場合は、そのパスを指定します。parts フォルダにある content-page.php を組み込む場合は以下のように記述します。

<?php get_template_part( 'parts/content', 'page' ); ?>

以下がソースです。

最初にアクションフック get_template_part_{$slug} が実行されます。

$name が指定されていれば、配列の変数 $templates に {$slug}-{$name}.php と言うファイル名を格納し、続いて変数 $templates に {$slug}.php と言うファイル名を格納しています。

変数 $templates を引数にして locate_template() を実行してファイルを読み込みます。locate_template() は引数に与えられたファイル名の配列を使って順番にファイルを検索して、ファイルが見つかれば読み込みます。

locate_template() の内部ではファイルを読み込むために load_template() が呼び出されています。

function get_template_part( $slug, $name = null ) {
  /**
   * Fires before the specified template part file is loaded.
   *
   * The dynamic portion of the hook name, `$slug`, refers to the slug name
   * for the generic template part.
   *
   * @since 3.0.0
   *
   * @param string      $slug The slug name for the generic template.
   * @param string|null $name The name of the specialized template.
   */
  do_action( "get_template_part_{$slug}", $slug, $name );

  $templates = array();
  $name = (string) $name;
  if ( '' !== $name )
    $templates[] = "{$slug}-{$name}.php";

  $templates[] = "{$slug}.php";

  locate_template($templates, true, false);
}
テンプレートパーツで変数を参照

get_template_part() などの関数(インクルードタグ)で読み込まれたテンプレートパーツは、その内部からは呼び出し元(index.php など)で定義された変数を参照できません(PHP の言語仕様上、関数の外のスコープを参照することができない)。

WordPress の関数を使わずに、直接 PHP の include や require を使ってインクルードすれば読み込まれた側でも変数を参照できますが、通常テンプレートファイルを読み込む場合(functions.php は別ですが)、このような使い方はしません。

<?php 
  $my_val = "My Value";
  //通常このような使い方はしません
  include(get_theme_file_path('content-test.php'));
?>

解決策としては、呼び出し元で set_query_var() を使って変数をテンプレートパーツで使えるようにし、テンプレートパーツ側で get_query_var() を使って参照します(テンプレートに変数を渡す)。

呼び出し元のファイルで set_query_var() の第一引数に参照する値の「キー名」を指定し、第二引数に参照したい「値」を指定します。

//呼び出し元ファイル(index.php など)
<?php 
  set_query_var( 'my_val', "My Value !"); 
  get_template_part('content', 'page');
?>

テンプレートパーツ側では get_query_var() の引数に、set_query_var() で指定した「キー名」を指定します。

//content-page.php (読み込まれるテンプレートパーツ)
<p><?php echo get_query_var('my_val'); ?></p>

//以下が出力されます
//My Value ! 

グローバル変数の利用

グローバル変数を使うと、例えば header.php などのテンプレートパーツで呼び出し元(index.php など)で定義された変数を参照することができます。但し、グローバル変数を使う場合は WordPress やプラグインのグローバル変数と重複しないように注意する必要があります。

呼び出し元(index.php など)では、変数を global 宣言してから値を代入し、get_header() や get_template_part() などのインクルードタグを実行します。

//呼び出し元(index.php など)
<?php global $my_val; $my_val = "My Value !"; ?>
<?php get_template_part('content'); ?>

読み込まれるテンプレートパーツ側でも、使用する前に global 宣言する必要があります。

//content.php (読み込まれるテンプレートパーツ)
<p><?php global $my_val; echo $my_val; ?></p>

locate_template

指定されたテンプレートファイルが存在するか確認し、見つかればテンプレートのファイル名を返します。パラメータ $load が true の場合は、見つかったテンプレートファイルを読み込みます。

locate_template( $template_names, $load, $require_once )

パラメータ
  • $template_names(文字列|配列):(必須) 検索するテンプレートファイルを優先度順に並べた配列または文字列。(拡張子が必要。)
  • $load(真偽値):(オプション) true を指定すると、見つかったテンプレートファイルを読み込みます。初期値: false
  • $require_once(真偽値):(オプション) true なら PHP の require_once 関数でテンプレートファイルを読み込みます。false なら PHP の require 関数を使います。$load が false(デフォルト)の時は無視されます。 初期値: true
戻り値
見つかればテンプレートのパスを含むファイル名を返し、見つからなければ空文字列を返します。

以下がソースです。$template_names で指定されたファイルを file_exists() で順番に検索します。また、検索するディレクトリは以下の順になっていて、そのディレクトリにファイルが存在すればそのファイルを変数 $located に格納します。

  1. STYLESHEETPATH(現在のテーマまたは子テーマのスタイルシートのディレクトリ)
    get_stylesheet_directory() で取得するパスのディレクトリ

  2. TEMPLATEPATH(現在の親テーマのディレクトリ)
    get_template_directory() で取得するパスのディレクトリ

  3. ABSPATH . WPINC . '/theme-compat/'(/wp-include/theme-compat/ )
    ※ theme-compat は WordPress デフォルトのテーマファイル(header.php や footer.php、sidebar.php など)が入っているディレクトリです。

$load が true の場合は、load_template() でファイルを読み込み、そうでなければパスを含むファイル名を返します。ファイルが見つからない場合は、$located が 「''」なので空文字列を返します。

function locate_template($template_names, $load = false, $require_once = true ) {
  $located = '';
  foreach ( (array) $template_names as $template_name ) {
    if ( !$template_name )
      continue;
    if ( file_exists(STYLESHEETPATH . '/' . $template_name)) {
      $located = STYLESHEETPATH . '/' . $template_name;
      break;
    } elseif ( file_exists(TEMPLATEPATH . '/' . $template_name) ) {
      $located = TEMPLATEPATH . '/' . $template_name;
      break;
    } elseif ( file_exists( ABSPATH . WPINC . '/theme-compat/' . $template_name ) ) {
      $located = ABSPATH . WPINC . '/theme-compat/' . $template_name;
      break;
    }
  }

  if ( $load && '' != $located )
    load_template( $located, $require_once );

  return $located;
}

STYLESHEETPATH などの定数は「wp-include/default-constants.php」に定義されています。

WPINC は「wp-settings.php」で「define( 'WPINC', 'wp-includes' )」のように定義されています。

ABSPATH は WordPress がインストールされている(wp-load.php または wp-config.php が置かれている)ディレクトリのフルパスが入っている定数です。WordPress がインストールされているディレクトリにある wp-load.php wp-config.php で以下のように定義されています。

 // wp-load.php 抜粋 
define( 'ABSPATH', dirname( __FILE__ ) . '/' );
require_once( ABSPATH . 'wp-config.php' );
// wp-config.php 抜粋
if ( !defined('ABSPATH') )
  define('ABSPATH', dirname(__FILE__) . '/');

dirname() は親ディレクトリのパスを返す関数で、 __FILE__ はファイルのフルパスとファイル名を表すマジック定数なので、ABSPATH の値は wp-config.php がインストールされているディレクトリのフルパスになります(最後に「/」が付いています)。

load_template

PHP の require_once() または require() を使って WordPress 環境へテンプレートファイルを読み込みます。

load_template( $_template_file, $require_once )

パラメータ
  • $_template_file(文字列):(必須) テンプレートファイルのパス。
  • $require_once(真偽値):(オプション) require_once を使うか require を使うかの指定。 初期値: true(require_once を使う)
戻り値
なし

以下がソースです。

2行目:テンプレートパーツでこれらの変数を利用できるようにグローバルとして宣言。

5行目: PHP の extract() を使ってクエリ変数($wp_query->query_vars)を連想配列から連想配列のキーを変数名とする変数を生成(抽出)しています。

8~10行目は、isset() で検索キーワード($s)がセットされているかを確認して、セットされていればエスケープ処理しています。

12~16行目で第二引数の値により、require_once() または require() を使ってテンプレートファイルを読み込んでいます。

function load_template( $_template_file, $require_once = true ) {
  global $posts, $post, $wp_did_header, $wp_query, $wp_rewrite, $wpdb, $wp_version, $wp, $id, $comment, $user_ID;

  if ( is_array( $wp_query->query_vars ) ) {
    extract( $wp_query->query_vars, EXTR_SKIP );
  }

  if ( isset( $s ) ) {
    $s = esc_attr( $s );
  }

  if ( $require_once ) {
    require_once( $_template_file );
  } else {
    require( $_template_file );
  }
}

以下はテンプレートで「mytemplate.php」と言うファイルを読み込んで、「mytemplate.php」でテンプレートで set_query_var() を使って設定した変数を使えるようにする例です。

※但し、これはこの関数の説明のためのサンプルで、実際のテンプレートパーツの読み込みは、get_template_part() を使うほうが良いかと思います。get_template_part() の内部では load_template() が使われています。

locate_template() を使って「mytemplate.php」がテーマディレクトリに在るかを検索し、ファイルがあれば load_template() で読み込んでいます。

<?php
$template = locate_template('mytemplate.php');

if( $template ){
  set_query_var('my_var', 'Hello My Template!' );
  load_template( $template );
}
?>

mytemplate.php で以下のように get_query_var() で変数の値を取得して echo すると「Hello My Template!」と出力されます。

<?php echo get_query_var('my_var'); ?>

シンボルテーブルについては「変数管理の基礎(PHPの参照とは何か)-PHP変数管理 (2)」に詳しい解説があります。また、「参照カウント法の原理」でも触れられています。

テンプレートで必須の関数

以下の wp_head() と wp_footer() はテーマのテンプレート(header.php や footer.php)に必須の関数です。記述しないとテーマが正常に機能しない可能性が高いです。

テンプレートでよく使われる関数

body_class

<body> タグにページ種類に応じた class 属性を出力する関数です。ページの種類に応じて、body 要素の class 属性にクラスを割り当てたい場合に利用します。

body_class( $class )

パラメータ
$class (string|array) :追加クラス名(オプション)
戻り値
なし
利用可能箇所
どこでも可能

基本的な使い方は、以下のように <body> タグ内に記述します。

<body <?php body_class(); ?>>
          
//以下はメインページでの出力例
<body class="home blog">

出力されるクラス名は、テンプレートの種類やログイン状態などにより異なります。

以下は body_class() で出力される class 属性の例です。 スタイルシートに予めこれらのクラスを定義しておくことで、ページの種類やログイン状態によりスタイルを変更することができます。

どのような class 属性が出力されるかは、get_body_class() のソース(定義)で確認することができます。

body_class 関数で出力される class 属性(主な例)
ページの種類 class 属性の値
メインページ home blog
投稿の個別ページ single single-post postid-投稿のID
カスタム投稿タイプの個別ページ single single-カスタム投稿タイプ postid-投稿のID
固定ページ page page-id-固定ページのID page-template page-template-テンプレート名
カテゴリーのアーカイブページ archive category category-カテゴリーのスラッグ
タグのアーカイブページ archive tag tag-タグのスラッグ
日付系のアーカイブページ archive date
ユーザーのアーカイブページ archive author authro-ユーザー名
検索結果のページ search
検索結果がある場合: search-results
検索結果がない場合: search-no-results

ログインしている場合は、以下のような「logged-in」などのクラスが出力されます。

//以下はログイン状態でのメインページでの出力例
<body class="home blog logged-in admin-bar no-customize-support">

例えばログインしている場合のみ表示したい内容があれば、以下のような方法で実現できます。動的に出力されるクラスを利用することで色々と応用できるかも知れません。

<div class="admin_section">
  ログイン時のみ表示する内容
</div>
body .admin_section {
  display: none;
}
body.logged-in .admin_section {
  display: block;
}

追加クラスの指定

オプションの引数($class)を指定すれば、body 要素に独自のクラスを追加することができます。

複数のクラスを追加する場合は、クラス名の間をスペースで区切って指定します。

<body <?php body_class('my-class'); ?>>

//メインページでの出力例(my-class が追加されます)
<body class="home blog my-class">

フィルターフックを使ったクラスの追加

'body_class' フィルターフックを使って、独自のクラスを追加することができます。

追加したいクラスを配列 $classes に追加して返す関数を作成して add_filter() で 'body_class' に登録します。以下は my-class と言うクラスを追加する例です。

add_filter( 'body_class', 'add_my_classes' );
function add_my_classes( $classes ) {
  $classes[] = 'my-class';
  return $classes;
} 

以下のように記述しても上記と同じことになります。

add_filter( 'body_class', 'add_my_classes' );
function add_my_classes( $classes ) {
  return array_merge( $classes, array( 'my-class' ) );
} 

フィルターフックを使うと、特定の条件でクラスを追加することができます。

以下は、カテゴリーが「music」の場合、その一覧ページと個別ページに「music」というクラスを追加する例です。デフォルトでは、body_class() によって一覧ページと個別ページに共通のクラスは出力されません。

add_filter('body_class', 'add_my_classes');
function add_my_classes($classes) {
 if(in_category('music')) {  //カテゴリーが「music」の場合
  $classes[] = 'music';//「music」というクラスを(配列 $classes[] に)追加
 }
 return $classes;
} 

以下は固定ページまたは投稿(及びカスタム投稿)の場合にページのスラッグをクラスに追加する例です。(関連ページ:スラッグを取得

但し、この場合パーマリンク設定で %postname% を使用していて、スラッグは半角英数字で指定してある必要があります。

add_filter( 'body_class', 'add_my_classes' );
function add_my_classes( $classes ) {
  if ( is_page() || is_single() ) {
    $classes[] = get_post( get_the_ID() )->post_name;
  } 
  return $classes;
} 

以下は is_singular() を使って個別ページ(投稿、カスタム投稿、固定ページ、添付ファイル)の場合にスラッグをクラスに追加する例です。

add_filter( 'body_class', 'add_my_classes' );
function add_my_classes( $classes ) {
  if ( is_singular() ) {
    $classes[] = get_post( get_the_ID() )->post_name;
  } 
  return $classes;
} 

以下は、投稿の個別ページの場合は、投稿のスラッグ及び属する全てのカテゴリーのスラッグをクラスに追加する例です。

add_filter( 'body_class', 'add_my_classes' );
function add_my_classes( $classes ) {
  if(is_single()) {
    global $post;
    $classes[] = get_post( $post->ID  )->post_name;
    foreach ( ( get_the_category( $post->ID ) ) as $category ) {
      $classes[] = $category->category_nicename;
    }
  } 
  return $classes;
}

複数の処理を記述することもできます。$classes[] にクラスを追加して、最後に必ず $classes を return します。以下は公式テーマ「twentynineteen」の template-functions.php の例です。

function twentynineteen_body_classes( $classes ) {

  if ( is_singular() ) {
    // Adds `singular` to singular pages.
    $classes[] = 'singular';
  } else {
    // Adds `hfeed` to non singular pages.
    $classes[] = 'hfeed';
  }

  // Adds a class if image filters are enabled.
  if ( twentynineteen_image_filters_enabled() ) {
    $classes[] = 'image-filters-enabled';
  }
  //最後に必ず return します
  return $classes;
}
add_filter( 'body_class', 'twentynineteen_body_classes' );

クラスの削除

body_class() によって自動的に出力されるクラスを削除したい場合は、フィルターを使って以下のようにすると削除することができます。「class-to-remove」に削除したいクラスの文字列を指定します。

add_filter( 'body_class', function( $classes ) {
  foreach($classes as $key => $class) {
    if( $class == "class-to-remove" ){
      unset($classes[$key]);
    }
  }
  return $classes;
});

前述の例では、無名関数を使用していますが以下のように記述することもできます。

add_filter( 'body_class', 'remove_default_classes');
function remove_default_classes( $classes ) {
  foreach($classes as $key => $class) {
    if( $class == "class-to-remove" ){
      unset($classes[$key]);
    }
  }
  return $classes;
};

関連ページ:スラッグを取得/スラッグを id や class として出力

post_class

投稿に応じた class 属性を出力する関数です。

ループ内で <div <?php post_class(); ?> > のように記述すると、div タグにいろいろな投稿関連のクラス(表示される投稿に依存)が出力されます。

ループの外で使う場合は、第2引数に投稿の ID または投稿オブジェクトを指定します。

post_class( $class, $post_id )

パラメータ
  • $class (string|array):(オプション) クラス属性へ追加するクラス。複数ある場合で文字列の場合は半角スペースで区切って指定。初期値: 空文字列
  • $post_id (int|WP_Post): (オプション) 投稿 ID または投稿オブジェクト。デフォルトは現在の投稿( global $post)。初期値: null
戻り値
なし

基本的な使い方は、以下のように div などの HTML タグに記述してクラスを出力します。

<section <?php post_class(); ?>>
            
<!-- 投稿個別ページの場合の出力例 --> 
<section class="post-72 post type-post status-publish format-standard hentry category-news tag-music">

<!-- 固定ページの場合の出力例 -->
<section class="post-2 page type-page status-publish hentry">

ページの種類により異なりますが、以下のようなクラスが出力されます。

  • post-[id]
  • [post-type]
  • type-[post-type]
  • status-[post-status]
  • format-[post-format] (default to 'standard')
  • post-password-required
  • post-password-protected
  • has-post-thumbnail
  • sticky
  • hentry (hAtom microformat pages)
  • [taxonomy]-[taxonomy-slug]
  • category-[category-slug]
  • tag-[tag-name]
ページの種類に応じて出力されるクラス
投稿が表示されているページ 出力する CSS クラス
フロントページ(固定でもそうでなくても) post post-(投稿 ID) hentry
単一投稿のページ post post-(投稿 ID) hentry
先頭固定表示が指定されている投稿 sticky
作成者(アーカイブ)のページ post post-(投稿 ID)
カテゴリー(アーカイブ)のページ post post-(投稿 ID) category-カテゴリーのスラッグ
投稿タグ(アーカイブ)のページ post post-(投稿 ID) tag-投稿タグのスラッグ
アーカイブ(年、月、日)のページ post post-(投稿 ID)
検索結果のページ post post-(投稿 ID)
添付ファイルのページ attachment post-(投稿 ID)
ページフォーマットを選択している投稿 format-ページのフォーマット名

追加クラスの指定

オプションの引数($class)を指定すれば、デフォルトで出力されるクラスに加えて独自のクラスを追加することができます。

複数のクラスを追加する場合は、配列で指定するか文字列の場合はクラス名の間をスペースで区切って指定します。

<div <?php post_class('my-class'); ?>>

<div <?php post_class('foo bar'); ?>>

<div <?php post_class(array('foo', 'bar', 'boo')); ?>>

ループの外で使う場合

ループの外や独自のループの中で使用する場合は、第2パラメータに投稿 ID を指定でき、指定した ID の投稿に基づいてクラスが出力されます。

個別ページの場合は、表示される投稿は1つなのでループの中でも外でもグローバル変数 $post は通常同じですが、カテゴリーページなどのアーカイブページではループの外と内では $post は書き換わっているので、ループの開始前に出力されるクラスとループの終了後に出力されるクラスが異なります。

<body>
  <div id="wrapper" <?php post_class(); ?>><!-- ループ前の $post に基づいて出力 -->
   ・・・
    <?php if(have_posts()) : ?>
      <?php while(have_posts()) : the_post(); ?>
        <div <?php post_class(); ?>><!-- 投稿ごとに出力されるクラスが変わる -->
          <?php the_content(); ?>
        </div>
       <?php endwhile; ?>
     <?php endif; ?>
   ・・・
  <div id="side" <?php post_class(); ?>><!-- ループ後の $post に基づいて出力 -->

上記のような場合にループの前後(2行目と12行目)で同じクラスを出力するようにする方法の1つは、テンプレートの先頭などでその時点のグローバル変数 $post の ID を変数に保存します。

但し、出力されるクラスはそのページの最初の投稿に基づいたクラスになるので、アーカイブページなどでこのような使い方が有用かどうかはわかりません(あまり意味が無いかと思われますが参考まで)。

<body>
  <?php $my_initial_id = $post->ID; ?><!-- 最初の投稿の ID を変数に保存 -->
  <div id="wrapper" <?php post_class('', $my_initial_id); ?>><!-- 取得した ID を指定 -->
   ・・・
    <?php if(have_posts()) : ?>
      <?php while(have_posts()) : the_post(); ?>
        <div <?php post_class(); ?>><!-- 投稿ごとに出力されるクラスが変わる -->
          <?php the_content(); ?>
        </div>
       <?php endwhile; ?>
     <?php endif; ?>
   ・・・
 <div id="side" <?php post_class('', $my_initial_id); ?>><!-- 取得した ID を指定 -->

フィルターでクラスを追加

body_class() 同様、post_class() でもフィルターフックを使ってクラスを追加することができます。

post_class() の場合は 'post_class' フィルターフックを使います。

以下は post_class() を記述した要素のクラス属性へその投稿が属する全てのカテゴリーのスラッグを追加する例です。以下は functions.php に記述します。

function my_add_category_post_class( $classes ) {
  global $post;
  foreach ( ( get_the_category( $post->ID ) ) as $category ) {
    $classes[] = $category->category_nicename;
  }
  return $classes;
}
add_filter( 'post_class', 'my_add_category_post_class' );

関連ページ:スラッグを class として出力

edit_post_link

ユーザーがログインしていて投稿の編集権限がある場合に現在の投稿の編集用リンクを出力します。

WordPress にログインしている場合に表示される上部のツールバーを非表示にしている場合などに便利です。

edit_post_link( $link, $before, $after, $id, $class )

パラメータ
  • $link(文字列):(オプション)リンクのテキスト。 初期値: __('Edit This')。日本語の場合は「編集」
  • $before(文字列):(オプション)リンクのテキストの前に出力するコードやテキスト。初期値: 空文字列
  • $after(文字列):(オプション)リンクのテキストの後に出力するコードやテキスト。初期値: 空文字列
  • $id(整数|WP_Post):(オプション)投稿 ID または投稿オブジェクト。初期値:global $post
  • $class(文字列) (オプション) リンクの CSS クラス名 (WordPress 4.4 で追加)。初期値: post-edit-link
戻り値
なし
利用可能箇所
ループの外で使用する場合は投稿の ID を渡す必要があります。

パラメータを指定せずに個別ページのテンプレートなどに記述すると以下のような「編集」と言うリンク(post-edit-link クラスが付与された a 要素)が出力されます。

<?php edit_post_link(); ?>
          
<!-- 以下のようなリンクが出力される -->         
<a class="post-edit-link" href="http://localhost/wp-admin/post.php?post=1163&amp;action=edit">編集</a>

以下はリンク文字を指定して p 要素で囲んで出力する例です。

<?php edit_post_link('この記事を編集','<p class="my_edit_link">','</p>'); ?>
          
<!-- 以下のように出力される -->         
<p class="my_edit_link"><a class="post-edit-link" href="http://localhost/wp-admin/post.php?post=1163&amp;action=edit">この記事を編集</a></p>

Codex には「ループの外の場合、投稿の ID を渡す必要があります。」とありますが、global $post が何らかの理由で書き換えられていなければ問題がない場合が多いと思います。

もし指定する場合は、get_queried_object() を使って以下のように記述すれば良いかと思われます。第4パラメータはオブジェクトも指定できるので get_queried_object() のみで大丈夫のようです。

<?php edit_post_link('この記事を編集','<p class="my_edit_link">','</p>', get_queried_object()->ID); ?>

以下はリンク(a 要素)のクラスを第5パラメータで「my-class」に指定する例です。この例では第4パラメータに get_queried_object() を指定していますが、null や $post、空文字でも大丈夫なようでした。

<?php edit_post_link('この記事を編集','<p>','</p>', get_queried_object(), 'my-class'); ?>

<!-- 以下のように出力される -->
<p><a class="my-class" href="http://localhost/wp-admin/post.php?post=1163&amp;action=edit">この記事を編集</a></p>

以下は header.php に記述して投稿の個別ページまたは固定ページの場合に編集リンクを表示する例です。

<?php if(is_single() || is_page()) edit_post_link('この記事を編集','<p>','</p>'); ?>

必要であれば、第4パラメータに投稿 ID やオブジェクトを指定します。

<?php if(is_single() || is_page()) edit_post_link('この記事を編集','<p>','</p>', get_queried_object()->ID); ?>

以下は edit_post_link() のソースです。

function edit_post_link( $text = null, $before = '', $after = '', $id = 0, $class = 'post-edit-link' ) {
  if ( ! $post = get_post( $id ) ) {
    return;
  }

  if ( ! $url = get_edit_post_link( $post->ID ) ) {
    return;
  }

  if ( null === $text ) {
    $text = __( 'Edit This' );
  }

  $link = '<a class="' . esc_attr( $class ) . '" href="' . esc_url( $url ) . '">' . $text . '</a>';

  /**
  * Filters the post edit link anchor tag.
  * @since 2.3.0
  * @param string $link    Anchor tag for the edit link.
  * @param int    $post_id Post ID.
  * @param string $text    Anchor text.
  */
  echo $before . apply_filters( 'edit_post_link', $link, $post->ID, $text ) . $after;
}

クエリ変数

以下は WordPress Query Vars からの引用です。

「クエリ変数(Query vars)は、WordPress の投稿のクエリを定義します」とあり、デフォルトのパーマリンク設定では投稿の URL 中にクエリ変数が含まれています。

例えば http://example.com/?p=1 の場合、p と言うクエリ変数は 1 にセットされていて、これにより投稿 ID が 1 の投稿が表示されます。

デフォルト以外(pretty permalinks)のパーマリンク設定では URL にクエリ変数は含まれていません。

また、クエリ変数は WP_Query に渡されます。

Query vars define a query for WordPress posts.

When ugly permalinks are enabled, query variables can be seen in the URL. For example, in the URL http://example.com/?p=1 the p query var is set to 1, which will display the single post with an ID of 1.

When pretty permalinks are enabled, URLs don't include query variables. Instead, WordPress transforms the URL into query vars via the Rewrite API, which are used to populate the query.

Relationship to WP_Query

Query vars are fed into WP_Query, WordPress' post querying API.

WordPress Query Vars(日本語 Codex)

set_query_var

メインクエリの指定したクエリ変数に値をセットします。

set_query_var( $var, $value )

パラメータ
  • $var(文字列):(必須) クエリ変数を指定するキー。
  • $value(mixed):(必須) クエリ変数にセットする値。
戻り値
なし

set_query_var は グローバル $wp_query オブジェクトのメソッド set を使用するラッパー関数です。以下がソースです。

function set_query_var( $var, $value ) {
  global $wp_query;
  $wp_query->set( $var, $value );
}

get_template_part() 関数で読み込まれたテンプレートパーツで、呼び出し元で定義された変数を参照する場合などに使用します。

// get_template_part() で my-template.php を読み込む側のファイル
set_query_var('my_postid', $post->ID);
get_template_part('my-template');
// my-template.php で呼び出し元で定義した変数を参照
$my_postid = get_query_var('my_postid');  //呼び出し元の投稿 ID

get_query_var

グローバル変数 $wp_query に格納されているプロパティ query_vars(クエリ変数)から指定したキーの値を取得する関数です。

query_vars(配列)には URL(正確には $query)から解析されたキーと値のペアが入っていて、ページの種類やパーマリンク設定により取得される値が異なります(各ページで取得できる値)。

get_query_var( $var, $default )

パラメータ
  • $var(string):(必須)取得する変数のキー(変数名)
  • $default(mixed):(オプション)変数が設定されていない(存在しない)場合に戻す値。初期値: 空の文字列
戻り値
指定された変数の値。変数が設定されていない場合は $default を返します。
利用可能箇所
どこでも可能 。ただし、functions.php で使用する場合、記事の検索が行われる前に実行すると検索関連の変数は設定されてないため、戻り値は必ず '' となります。また、「パーマリンクの設定」やページの種類により得できる値が異なります。

クエリ変数(query variables)には $public_query_vars と $private_query_vars があり WP クラスのプロパティとして wp-includes/class-wp.php に定義されています。

但し、get_query_var() は WP_Query クラスで認識されている(WP_Query のインスタンスが生成される際に作られる)「クエリ変数 query_vars」のみを取得します。

class WP {
  /**
   * Public query variables.
   * Long list of public query variables.
   * @since 2.0.0
   * @var string[]
   */
  public $public_query_vars = array( 'm', 'p', 'posts', 'w', 'cat', 'withcomments', 'withoutcomments', 's', 'search', 'exact', 'sentence', 'calendar', 'page', 'paged', 'more', 'tb', 'pb', 'author', 'order', 'orderby', 'year', 'monthnum', 'day', 'hour', 'minute', 'second', 'name', 'category_name', 'tag', 'feed', 'author_name', 'static', 'pagename', 'page_id', 'error', 'attachment', 'attachment_id', 'subpost', 'subpost_id', 'preview', 'robots', 'taxonomy', 'term', 'cpage', 'post_type', 'embed' ); 
  
  /**
   * Private query variables.
   * Long list of private query variables.
   * @since 2.0.0
   * @var string[]
   */
  public $private_query_vars = array( 'offset', 'posts_per_page', 'posts_per_archive_page', 'showposts', 'nopaging', 'post_type', 'post_status', 'category__in', 'category__not_in', 'category__and', 'tag__in', 'tag__not_in', 'tag__and', 'tag_slug__in', 'tag_slug__and', 'tag_id', 'post_mime_type', 'perm', 'comments_per_page', 'post__in', 'post__not_in', 'post_parent', 'post_parent__in', 'post_parent__not_in', 'title', 'fields' );
  

Codex: Query Vars (public query variable)

add_query_arg() を使って URL に付け加えたカスタムクエリ変数などを get_query_var() で使用(取得)するには、それらを query_vars フィルターを使ってクエリ変数に追加する必要があります。

以下は get_query_var() で取得できる変数のキー(変数名)の一部抜粋です。

デフォルトではキーの文字列はシステム側で用意されたものだけです。(追加することは可能)

また、パーマリンク設定により取得されるキーの(有効な)値は異なります。

変数名(キー) 値の型 意味
cat string カテゴリID
category_name string カテゴリ名
category__and array すべてに該当するカテゴリIDの配列
category__in array 該当するカテゴリIDの配列
category__not_in array 除外するカテゴリIDの配列
meta_key string カスタムフィールドの名前
meta_value string カスタムフィールドの値
order string 並び順
orderby string 並び順を決める項目名
p int 投稿の ID
paged int アーカイブページでのページ分割時のページ番号
最初のページの場合は 0。2ページ目以降はページの番号
page int 個別ページ(静的フロントページ)でのページ分割時のページ番号
最初のページの場合は 0。2ページ目以降はページの番号
post__in array 該当する投稿情報(オブジェクト)IDの配列
post__not_in array 除外する投稿情報(オブジェクト)IDの配列
posts_per_page int 1ページの投稿数
s string 検索キーワード
tag string 投稿タグ名
tag_id int 投稿タグID
tag__and array すべてに該当する投稿タグIDの配列
tag__in array 該当する投稿タグIDの配列
tag__not_in array 除外する投稿タグIDの配列
tag_slug__and array すべてに該当する投稿タグスラッグの配列
tag_slug__in array 該当する投稿タグスラッグの配列
monthnum int 月の数値(日付アーカイブページのみ)
year int 年の数値(日付アーカイブページのみ)
taxonomy string カスタムタクソノミー名
post_type string (カスタム)投稿タイプ名
author string 投稿者 ID
author_name string 投稿者名

$wp_query の query_vars プロパティは以下のようにして確認することができます。

<?php var_dump($wp_query->query_vars); ?>

以下は投稿の個別ページでの出力例です。

array(65) {
  ["page"]=>int(0)
  ["name"]=>string(10) "first-post"
  ["category_name"]=>string(5) "music"
  ["error"]=>string(0) ""
   ・・・中略・・・
  ["monthnum"]=>int(0)
  ["year"]=>int(0)
  ["w"]=>int(0)
  ["tag"]=>string(0) ""
  ["cat"]=>string(0) ""
  ["tag_id"]=>string(0) ""
  ["author"]=>string(0) ""
   ・・・中略・・・
  ["paged"]=>int(0)
  ["meta_key"]=>string(0) ""
  ["meta_value"]=>string(0) ""
   ・・・中略・・・
  ["category__in"]=>array(0) {}
  ["category__not_in"]=>array(0) {}
  ["category__and"]=>array(0) {}
  ["post__in"]=>array(0) {}
  ["post__not_in"]=>array(0) {}
  ["post_name__in"]=>array(0) {}
  ["tag__in"]=>array(0) {}
  ["tag__not_in"]=>array(0) {}
  ["tag__and"]=>array(0) {}
   ・・・中略・・・
  ["post_type"]=>string(0) ""
  ["posts_per_page"]=>int(10)
  ["nopaging"]=>bool(false)
  ["comments_per_page"]=>string(2) "50"
  ["no_found_rows"]=>bool(false)
  ["order"]=>string(4) "DESC"
}

各ページで取得できる値

$wp_query->query_vars で取得できる値を確認してみると、ページの種類やパーマリンクの設定により取得できる値が異なることがわかります。

例えば、パーマリンク設定が「投稿名(/%postname%/)」の場合に、個別ページで以下を実行しても何も表示されません。

<?php  echo get_query_var('category_name');  ?>

パーマリンク設定をカスタムの「/%category%/%postname%/」に設定して上記を実行すると、カテゴリー名が表示されます。

クエリ変数 p(投稿 ID)の場合はパーマリンク設定がデフォルトか数字ベースの場合でないと取得できません。

また、ページの種類によって取得できる値が異なります。

var_dump($wp_query->query_vars) で確認すると値が空文字や0の設定されていない変数も出力されるためあまり見やすくありません。

例えば、以下のような関数を作成して header.php で実行すると各ページで取得できるクエリ変数の値を確認しやすいかと思います(もっといい方法があるかと思いますが、取りあえず)。

function my_query_vars() {
  global $wp_query;
  $my_query_vars = $wp_query->query_vars;
  foreach($my_query_vars as $key => $val) {
    if(is_array($val)) {
      $counter = 0;
      foreach($val as $k => $v) {
        if($counter ===0 && $v) {echo "$key : (array) ";}
        if($v) {
          echo "$k : $v <br>";
        }
        $counter ++;
      }
    }else{
       if($val) {
          echo "$key : $val <br>";
        }
    }
  }
}

以下はパーマリンク設定が「投稿名(/%postname%/)」の場合に、ページによりどのような値が取得できるかを確認した結果です。

但し以下のキーと値は全てで同じなので、「フロントページ」の例以外は省略しています。

  • cache_results : 1
  • update_post_term_cache : 1
  • lazy_load_term_meta : 1
  • update_post_meta_cache : 1
  • posts_per_page : 10
  • comments_per_page : 50
  • order : DESC
パーマリンク設定が「投稿名 /%postname%/」の場合
ページの種類 取得できたクエリ変数
フロントページ
cache_results : 1
update_post_term_cache : 1
lazy_load_term_meta : 1
update_post_meta_cache : 1
posts_per_page : 10
comments_per_page : 50
order : DESC 
フロントページ(2ページ目)
paged : 2
以下の値は全てのページで同じ(以下では省略)
cache_results : 1
update_post_term_cache : 1
lazy_load_term_meta : 1
update_post_meta_cache : 1
posts_per_page : 10
comments_per_page : 50
order : DESC
投稿個別ページ
name : sample post
投稿個別ページ(分割時2ページ目)
page : 2
name : sample post 
固定ページ
pagename : about
name : about 
カスタム投稿タイプ個別ページ
rental : rental-test-6
post_type : rental
name : rental-test-6 
カテゴリーアーカイブ
category_name : news
cat : 1 
タグアーカイブ
tag : sample
tag_id : 6
tag_slug__in : (array) 0 : sample 
カスタムタクソノミーアーカイブ
rental_cat(固有の taxonomy slug) : small
taxonomy : rental_cat
term : small 
月別アーカイブ
year : 2019
monthnum : 6 
投稿者別アーカイブ
author_name : xxxx01
author : 1 

以下は投稿の個別ページで、パーマリンク設定が異なる場合に取得できるクエリ変数の例です。

投稿の個別ページ
パーマリンク設定 取得できたクエリ変数
基本(?p=123)
p : 1242
以下の値は全てのページで同じ(以下では省略)
cache_results : 1
update_post_term_cache : 1
lazy_load_term_meta : 1
update_post_meta_cache : 1
posts_per_page : 10
comments_per_page : 50
order : DESC 
日付と投稿名
year : 2019
monthnum : 6
day : 25
name : sample page 
月と投稿名
year : 2019
monthnum : 6
name : sample page 
数字ベース(投稿 ID)
p : 1242 
投稿名
name : sample page
カスタム構造(カテゴリ/投稿名)
/%category%/%postname%/
name : sample page
category_name : news 

以下は現在のページ送り番号を取得する例です。

<?php 
$paged = intval(get_query_var( 'paged', 1 )); 

//以下でもほぼ同じです。
$paged = $wp_query->get('paged') ? intval($wp_query->get('paged')) : 1;

//静的フロントページの場合は、'page' クエリ変数を使用
$page = intval(get_query_var( 'page', 1 )); 
?>

以下は previous_posts_link() を使って一覧ページのリンクを出力する際に「1ページの投稿数(posts_per_page)」を取得して「« 前の5件へ」のように表示する例です。

<?php previous_posts_link('&laquo; 前の'. get_query_var( 'posts_per_page') . '件へ'); ?>

以下が get_query_var() のソースです。

function get_query_var( $var, $default = '' ) {
  global $wp_query;
  return $wp_query->get( $var, $default );  //$wp_query の get() メソッド
}

以下は $wp_query の get() メソッドのソースです。query_vars から指定したキーの値を取得しています。

public function get( $query_var, $default = '' ) {
  if ( isset( $this->query_vars[ $query_var ] ) ) {
    return $this->query_vars[ $query_var ];
  }

  return $default;
}   

query_vars フィルター

独自のクエリ変数を get_query_var() で取得できるようにするには、それらを WP_Query が扱えるパブリッククエリ変数(WP_Query のインスタンスが生成される際に作られるクエリ変数 query_vars)に追加する必要があります。

query_vars フィルタを使うと、クエリが実行される前に独自のクエリ変数をクエリ変数 query_vars に追加することができるので get_query_var() で取得できるようになります。

add_query_arg() を使って URL に付け加えたカスタムクエリ変数などを get_query_var() で使用するには、このフィルターを使ってクエリ変数 query_vars に追加する必要があります。

フィルター関数 ( $qvars )

パラメータ
  • $qvars(配列):クエリ変数の配列(query_vars)
function フィルター関数 ( $qvars ) {
    //$qvars[] に変数を追加
    return $qvars; //独自クエリ変数を追加した配列を返す
}
add_filter( 'query_vars', 'フィルター関数名', priority );

カスタムクエリ変数の追加

以下は my_var と言う独自のクエリ変数(カスタムクエリ変数)を WP_Query のプロパティ query_vars に追加する例です。

function add_query_vars_filter( $vars ){
  $vars[] = "my_var";  //query_vars の配列に my_var を追加
  return $vars;  //独自クエリ変数を追加した配列を返す
}
add_filter( 'query_vars', 'add_query_vars_filter' );

query_vars に追加した独自のクエリ変数を削除するには、追加した記述を削除するだけです。

WP_Query のプロパティ query_vars はページ読み込みの際に毎回生成されるため、以下の2~3行目は冗長なので不要です。

function add_query_vars_filter( $vars ) {
  $vars[] = 'my_var';
  unset($vars['my_var'] );  //追加した my_var を削除
  $vars[] = 'my-value';  //新しいクエリ変数を追加
  return $vars;
}
add_filter( 'query_vars', 'add_query_vars_filter' );

//以下でも同じこと
function add_query_vars_filter( $vars ) {
  $vars[] = 'my-value';  //新しいクエリ変数を追加
  return $vars;
}
add_filter( 'query_vars', 'add_query_vars_filter' );

以下は query_vars フィルターが設置されている WP::parse_request() のソースからの抜粋です。

public function parse_request( $extra_query_vars = '' ) {
  global $wp_rewrite;
  
  ・・・中略・・・
  
   /**
   * Filters the query variables whitelist before processing.
   * Allows (publicly allowed) query vars to be added, removed, or changed prior
   * to executing the query. Needed to allow custom rewrite rules using your own arguments
   * to work, or any other custom query variables you want to be publicly available.
   * @since 1.5.0
   * @param string[] $public_query_vars The array of whitelisted query variable names.
   */
  $this->public_query_vars = apply_filters( 'query_vars', $this->public_query_vars );

  foreach ( get_post_types( array(), 'objects' ) as $post_type => $t ) {
    if ( is_post_type_viewable( $t ) && $t->query_var ) {
      $post_type_query_vars[ $t->query_var ] = $post_type;
    }
  }

    foreach ( $this->public_query_vars as $wpvar ) {
      if ( isset( $this->extra_query_vars[ $wpvar ] ) ) {
        $this->query_vars[ $wpvar ] = $this->extra_query_vars[ $wpvar ];
      } elseif ( isset( $_GET[ $wpvar ] ) && isset( $_POST[ $wpvar ] ) && $_GET[ $wpvar ] !== $_POST[ $wpvar ] ) {
        wp_die( __( 'A variable mismatch has been detected.' ), __( 'Sorry, you are not allowed to view this item.' ), 400 );
      } elseif ( isset( $_POST[ $wpvar ] ) ) {
        $this->query_vars[ $wpvar ] = $_POST[ $wpvar ];
      } elseif ( isset( $_GET[ $wpvar ] ) ) {
        $this->query_vars[ $wpvar ] = $_GET[ $wpvar ];
      } elseif ( isset( $perma_query_vars[ $wpvar ] ) ) {
        $this->query_vars[ $wpvar ] = $perma_query_vars[ $wpvar ];
      }

    if ( ! empty( $this->query_vars[ $wpvar ] ) ) {
      if ( ! is_array( $this->query_vars[ $wpvar ] ) ) {
        $this->query_vars[ $wpvar ] = (string) $this->query_vars[ $wpvar ];
      } else {
        foreach ( $this->query_vars[ $wpvar ] as $vkey => $v ) {
          if ( is_scalar( $v ) ) {
            $this->query_vars[ $wpvar ][ $vkey ] = (string) $v;
          }
        }
      }

      if ( isset( $post_type_query_vars[ $wpvar ] ) ) {
        $this->query_vars['post_type'] = $post_type_query_vars[ $wpvar ];
        $this->query_vars['name']      = $this->query_vars[ $wpvar ];
      }
    }
  }
  ・・・以下省略・・・

クエリ文字列

クエリ文字列は URL パラメーターとも呼ばれますが、サーバーに情報を渡すための URL の末尾に付ける文字列(パラメータ)のことです。

「?」を URL の末尾につけ、その後に「パラメーター=値」を続けます。複数のパラメーターを指定する場合は「&」を使用します。

add_query_arg

指定したクエリ文字列を追加(更新)した URL を返します。

戻り値の URL はエスケープされていないので、そのまま出力するとXSS攻撃に使用される可能性があるため、出力する際は必ずエスケープ処理する必要があります。

  • URLとして出力する場合: esc_url() を使用
  • リダイレクトする場合など HTTP ヘッダに含める場合: esc_url_raw() を使用

[セキュリティ脆弱性]add_query_arg() と remove_query_arg() の用法について

add_query_arg($key, $value, $url)

パラメータ
  • $key(文字列|配列):(必須) クエリ変数のキー、または連想配列。初期値: なし
  • $value(文字列):(オプション) クエリ変数の値 (第1パラメータが連想配列の場合は URL)。初期値: なし
  • $url(文字列):(オプション)対象の URL。初期値: $_SERVER['REQUEST_URI']

URL を省略するとプロトコル名やホスト名を除いた現在の URL($_SERVER['REQUEST_URI'])が使われます。

もし URL に同じキー名がある場合は値を更新し、ない場合は追加します。

値に false または null を指定するとそのキーと値のパラメータを削除します。

戻り値
クエリ文字列を付加した URL。(注意)戻り値の URL はエスケープ処理されていないので、出力する際は必ずエスケープ処理する必要があります。

第1パラメータにキー、第2パラメータに値を指定する場合の例

<?php 
  $new_url = add_query_arg( 'key', 'value', 'http://example.com' );
  echo esc_url($new_url);  
  //出力 http://example.com?key=value 
?>

以下は news と言うカテゴリーのアーカイブページで URL を省略した場合の例です。

$_SERVER['REQUEST_URI'] は http や https などのプロトコル名やサーバーのドメイン名(ホスト名)を除いた URL になります。

<?php 
  $new_url = add_query_arg( 'key', 'value' );
  echo esc_url($new_url);  
  //出力 /category/news/?key=value  
?>

以下は固定ページ(contact)で URL に get_permalink() を指定して完全な URL にクエリ文字列を追加して取得する例です。

<?php 
  $new_url = add_query_arg( 'key', 'value', get_permalink( get_the_ID() ) );
  echo esc_url($new_url);  
  //出力 http://example.com/contact/?key=value 
?>

第1パラメータに key=>value の連想配列のペアを指定して、第2パラメータに URL を指定する場合の例

<?php 
  $new_url = add_query_arg( array(
    'key1' => 'value1',
    'key2' => 'value2',
  ), 'http://example.com' );
  echo esc_url($new_url); 
  //出力 http://example.com?key1=value1&key2=value2 
?>

以下の場合、key1 のパラメータは削除され、key2 のパラメータは値が更新され、key3 のパラメータは新たに追加されます。

<?php 
  $new_url = add_query_arg( array(
    'key1' => false,
    'key2' => 'new2',
    'key3' => 'val3',
  ), 'http://example.com?key1=val1&key2=val2 ' );
  echo esc_url($new_url);  
  //出力 http://example.com?key2=new2&key3=val3 
?>

以下は、現在のページにクエリパラメータを付加したリンクを表示する例です。

例えば、カテゴリーのアーカイブページ(http://example.com/category/news/)の場合、表示されるリンク先は http://example.com/category/news/?sort=date になります。

<a href="<?php echo esc_url(add_query_arg(array('sort'=>'date'))); ?>">日付で並べ替え</a>

add_query_arg() を使って URL に付け加えたカスタムクエリ変数を get_query_var() で使用するには、query_vars フィルターを使ってクエリ変数に追加する必要があります。

以下は add_query_arg() のソースです。

function add_query_arg() {
  $args = func_get_args();
  if ( is_array( $args[0] ) ) {
    if ( count( $args ) < 2 || false === $args[1] ) {
      $uri = $_SERVER['REQUEST_URI'];
    } else {
      $uri = $args[1];
    }
  } else {
    if ( count( $args ) < 3 || false === $args[2] ) {
      $uri = $_SERVER['REQUEST_URI'];
    } else {
      $uri = $args[2];
    }
  }

  if ( $frag = strstr( $uri, '#' ) ) {
    $uri = substr( $uri, 0, -strlen( $frag ) );
  } else {
    $frag = '';
  }

  if ( 0 === stripos( $uri, 'http://' ) ) {
    $protocol = 'http://';
    $uri      = substr( $uri, 7 );
  } elseif ( 0 === stripos( $uri, 'https://' ) ) {
    $protocol = 'https://';
    $uri      = substr( $uri, 8 );
  } else {
    $protocol = '';
  }

  if ( strpos( $uri, '?' ) !== false ) {
    list( $base, $query ) = explode( '?', $uri, 2 );
    $base                .= '?';
  } elseif ( $protocol || strpos( $uri, '=' ) === false ) {
    $base  = $uri . '?';
    $query = '';
  } else {
    $base  = '';
    $query = $uri;
  }

  wp_parse_str( $query, $qs );
  $qs = urlencode_deep( $qs ); // this re-URL-encodes things that were already in the query string
  if ( is_array( $args[0] ) ) {
    foreach ( $args[0] as $k => $v ) {
      $qs[ $k ] = $v;
    }
  } else {
      $qs[ $args[0] ] = $args[1];
  }

  foreach ( $qs as $k => $v ) {
    if ( $v === false ) {
      unset( $qs[ $k ] );
    }
  }

  $ret = build_query( $qs );
  $ret = trim( $ret, '?' );
  $ret = preg_replace( '#=(&|$)#', '$1', $ret );
  $ret = $protocol . $base . $ret . $frag;
  $ret = rtrim( $ret, '?' );
  return $ret;
}

remove_query_arg

URL からクエリパラメータ(文字列)を削除します。add_query_arg() を使ってもパラメータを削除することができます(remove_query_arg() の内部では add_query_arg() が使われています)。

add_query_arg() 同様、戻り値の URL はエスケープされていないので、そのまま出力するとXSS攻撃に使用される可能性があるため、出力する際は必ずエスケープ処理する必要があります。

  • URLとして出力する場合: esc_url() を使用
  • リダイレクトする場合など HTTP ヘッダに含める場合: esc_url_raw() を使用

[セキュリティ脆弱性]add_query_arg() と remove_query_arg() の用法について

remove_query_arg( $key, $query )

パラメータ
  • $key(文字列|配列):(必須)削除するクエリパラメータのキーまたはキーの配列
  • $query(真偽値|文字列):(オプション)URL を指定。指定しない(初期値の)場合はプロトコル名やホスト名を除いた現在の URL($_SERVER['REQUEST_URI'])が使用されます。 初期値:false
戻り値
指定したクエリ文字列を削除した(更新した) URL

以下は、http://www.example.com/news/?details=value1&type=value2&date=value3 と言う URL のページの場合の例です。

第2パラメータの URL を省略しているので $_SERVER['REQUEST_URI'] が適用されプロトコル名やホスト名を除いた URL が返ります。

<?php 
  echo esc_url( remove_query_arg( 'details' ) );
  //出力 /news/?type=value2&date=value3 
  
  echo esc_url( remove_query_arg( array( 'details', 'type', 'date') ) )
  //出力 /news/
?>

以下は remove_query_arg() のソースです。

内部では add_query_arg() を使って値を false にして返しています。

function remove_query_arg( $key, $query = false ) {
  if ( is_array( $key ) ) { // removing multiple keys
    foreach ( $key as $k ) {
      $query = add_query_arg( $k, false, $query );
    }
    return $query;
  }
  return add_query_arg( $key, false, $query );
}

現在クエリされているオブジェクトの取得

WordPress では個々のテンプレートの処理に入る際は、既に投稿や固定ページ、アーカイブページなどの情報(WordPress が自動的に抽出したデータ)が読み込まれた状態になっています。

テンプレートファイルで get_queried_object() を使うと現在表示しているページのオブジェクトを取得することができます。

取得したオブジェクトのプロパティからページの情報を得ることができます。

get_queried_object

現在表示しているページ(リクエストしたページ)のオブジェクトを取得します。

get_queried_object()

パラメータ
なし
戻り値
ページリクエストに応じたオブジェクト
利用可能箇所
グローバル変数の $wp_query が生成後でなければ目的のオブジェクトは取得できないので、functions.php で使用する時はフックなどのタイミングに注意する必要があります(※)。

※ functions.php で使用する場合、例えば以下のように init や after_setup_theme、wp_loaded などのアクションフックを使うと「Notice: Trying to get property 'name' of non-object 」のような Notice が表示されます。

wp や wp_head など $wp_query 生成後のフックであれば問題ありません。

function my_queried_object() {
  $term_obj = get_queried_object(); 
  $term_name = $term_obj->name;
}
add_action('init' , 'my_queried_object');
//Notice が発生

以下が get_queried_object() のソースです。

function get_queried_object() {
  global $wp_query;
  return $wp_query->get_queried_object();
}

Codex に「$wp_query->get_queried_object() のラッパー関数です」とあるように、WP_Query クラスの get_queried_object() メソッドの実行結果を返しています。

WP_Query クラスの get_queried_object() メソッドのソースの冒頭を見ると以下のようになっていて、まず $wp_query の queried_object プロパティをチェックして値が設定されていればその値を返しています。

public function get_queried_object() {
  if ( isset( $this->queried_object ) ) {
    return $this->queried_object;
  }
  ・・・以下省略・・・
}

queried_object プロパティの値が設定されていない場合は、ページ(テンプレート)の種類により適切な関数で該当するオブジェクトを取得してそのプロパティを返しているようです。

以下はリクエストしたページで get_queried_object() によって取得されるオブジェクトの概要です。

get_queried_object の戻り値
リクエストページ 戻り値(概要)
投稿の個別ページ WP_Post オブジェクト(投稿の情報)
カスタム投稿タイプの個別ページ WP_Post オブジェクト(投稿の情報)
固定ページ WP_Post オブジェクト(固定ページの情報)
カテゴリー・タグ・タクソノミーのアーカイブページ WP_Term オブジェクト(タームの情報)
投稿タイプアーカイブページ WP_Post_Type オブジェクト(カスタム投稿タイプの情報)
投稿者アーカイブページ WP_User オブジェクト(投稿者の情報)
日付アーカイブページ null
トップページ null(トップページページを「固定ページ」に設定している場合は WP_Post オブジェクト)

カテゴリー・タグ・カスタムタクソノミーのアーカイブページでの使用例

カテゴリーやタグ、カスタムタクソノミーのアーカイブページ(category.php、tag.php、taxonomy.php など)でタームオブジェクトを使ってそれらに属する項目(ターム)の情報を取得することができます。

これらの情報は get_term() などの関数を使っても取得することができますが、get_queried_object() を使って取得したオブジェクトからも取得することができます。

以下はカテゴリーやタグ、カスタムタクソノミーのアーカイブページでターム(カテゴリーやタクソノミーの個々の項目)の情報を取得する例です。

タームの説明には HTML を記述することができるので、以下で取得する値には HTML が含まれている可能性があります。必要に応じてエスケープ処理します。

<?php
// タームオブジェクトを取得
$term_obj = get_queried_object(); 
// ターム ID
$my_term_id = $term_obj->term_id;
// タームのスラッグ
$term_slug =  $term_obj->slug; 
// タームのタイトル
$term_name = $term_obj->name; 
// タームの説明(HTML が含まれる可能性あり)
$term_description = $term_obj->description; 
// タームに属する記事数
$term_count = $term_obj->count;
?>
ページごとに取得されるオブジェクト

以下は get_queried_object() で取得できるオブジェクトについてです。

それぞれのテンプレートで以下のように get_queried_object() を実行して var_dump() で取得したオブジェクトの内容は以下のようになっています。

<pre><?php var_dump( get_queried_object() ); ?></pre>

グローバル変数 $wp_query の queried_object プロパティを見てもほぼ同じ値が入っていると思います。

<pre><?php var_dump( $wp_query->queried_object ); ?></pre>

投稿ページ

以下は投稿個別ページ(single.php)での実行結果です。WP_Post オブジェクトが取得されます。

object(WP_Post)#4419 (24) {  //WP_Post オブジェクト
  ["ID"]=>int(41)
  ["post_author"]=>string(1) "1"
  ["post_date"]=>string(19) "2019-01-03 08:57:35"
  ["post_date_gmt"]=>string(19) "2019-01-02 23:57:35"
  ["post_content"]=>string(730) "投稿のコンテンツ(省略)"
  ["post_title"]=>string(19) "投稿サンプル1"
  ["post_excerpt"]=>string(0) ""
  ["post_status"]=>string(7) "publish"
  ["comment_status"]=>string(4) "open"
  ["ping_status"]=>string(4) "open"
  ["post_password"]=>string(0) ""
  ["post_name"]=>string(10) "first-post"
  ["to_ping"]=>string(0) ""
  ["pinged"]=>string(0) ""
  ["post_modified"]=>string(19) "2019-04-25 11:14:43"
  ["post_modified_gmt"]=>string(19) "2019-04-25 02:14:43"
  ["post_content_filtered"]=>string(0) ""
  ["post_parent"]=>int(0)
  ["guid"]=>string(26) "http://localhost//?p=41"
  ["menu_order"]=>int(0)
  ["post_type"]=>string(4) "post"
  ["post_mime_type"]=>string(0) ""
  ["comment_count"]=>string(1) "0"
  ["filter"]=>string(3) "raw"
}

以下は WP_Post オブジェクト(投稿オブジェクト)のメンバー変数(プロパティ)の概要です。

WP_Post オブジェクト メンバー変数
プロパティ名 データ型 意味
ID int 投稿 ID
post_author string 投稿者ID
post_date string 投稿日時 (YYYY-MM-DD HH:MM:SS)
post_date_gmt string 投稿日時(GMT)(YYYY-MM-DD HH:MM:SS)
post_content string 投稿本文
post_title string 投稿タイトル
post_category int カテゴリー ID。※バージョン 2.1 以降は常に 0。投稿のカテゴリーを取得するには get_the_category() を使用
post_excerpt string 投稿の抜粋
post_status string 投稿状態(publish|pending|draft|private|static|object|attachment|inherit|future)
comment_status string コメント投稿状態(open|closed|registered_only)
ping_status string トラックバック/ピンバック受付状態(open|closed)
post_password string 閲覧パスワード
post_name string スラッグ / 投稿名(パーマリンク設定で%postname%使用時)
to_ping string ピン通知 URL
pinged string トラックバック送信先(ピン通知済み URL)
post_modified string 更新日時 (YYYY-MM-DD HH:MM:SS)
post_modified_gmt string 更新日時(GMT) (YYYY-MM-DD HH:MM:SS)
post_content_filtered string
post_parent int 親のポストID(0 は最上位の親)
guid string URL(投稿へのリンクの書式になっている識別子)
menu_order int 固定ページ の表示順序
post_type string 投稿情報タイプ(post|page|attachment|カスタム投稿タイプ)
post_mime_type string 添付ファイルの MIME タイプ(image/png など)
comment_count int コメント数
ancestors array 先祖のID 配列で保持 階層型ポストの場合のみ
filter string 適用されたフィルター名('raw'など)

固定ページ

以下は固定ページ(page.php)での実行結果です。投稿ページ同様 WP_Post オブジェクトが取得されています。

object(WP_Post)#354 (24) {  //WP_Post オブジェクト
  ["ID"]=>int(150)
  ["post_author"]=>string(1) "1"
  ["post_date"]=>string(19) "2019-03-28 14:56:08"
  ["post_date_gmt"]=>string(19) "2019-03-28 05:56:08"
  ["post_content"]=>string(973) "投稿のコンテンツ(省略)"
  ["post_title"]=>string(5) "About"
  ["post_excerpt"]=>string(0) ""
  ["post_status"]=>string(7) "publish"
  ["comment_status"]=>string(6) "closed"
  ["ping_status"]=>string(6) "closed"
  ["post_password"]=>string(0) ""
  ["post_name"]=>string(5) "about"
  ["to_ping"]=>string(0) ""
  ["pinged"]=>string(0) ""
  ["post_modified"]=>string(19) "2019-05-05 13:56:30"
  ["post_modified_gmt"]=>string(19) "2019-05-05 04:56:30"
  ["post_content_filtered"]=>string(0) ""
  ["post_parent"]=>int(0)
  ["guid"]=>string(33) "http://localhost/?page_id=150"
  ["menu_order"]=>int(0)
  ["post_type"]=>string(4) "page"
  ["post_mime_type"]=>string(0) ""
  ["comment_count"]=>string(1) "0"
  ["filter"]=>string(3) "raw"
}

カテゴリー・タグ・タクソノミーのアーカイブページ

以下はカスタムタクソノミーのアーカイブページ(taxonomy.php)での実行結果の例です。

object(WP_Term)#4429 (10) {  //WP_Term オブジェクト
  ["term_id"]=>int(31)
  ["name"]=>string(6) "東京"
  ["slug"]=>string(5) "tokyo"
  ["term_group"]=>int(0)
  ["term_taxonomy_id"]=>int(31)
  ["taxonomy"]=>string(10) "rental_tag"
  ["description"]=>string(0) ""
  ["parent"]=>int(0)
  ["count"]=>int(1)
  ["filter"]=>string(3) "raw"
}

以下はタームオブジェクトのプロパティの概要です。

タームオブジェクトのプロパティ
プロパティ名 内容 データ型
term_id ターム ID 整数
name タームの名前 文字列
slug タームのスラッグ 文字列
description タームの説明(HTML を含む可能性あり) 文字列
parent 親タームの ID。親タームがない場合は「0」を返す 整数
count そのタームに属する投稿数 整数
taxonomy タームが属するタクソノミーの名前。カテゴリーの場合は'category'、タグの場合は'post_tag'となる 文字列
term_group タームのグループ ID(親タームのターム ID/parent と同じ) 整数
term_taxonomy_id タームのタクソノミー ID(ターム ID と同じ値の場合も多いが、ターム ID とは異なるもの) 整数

投稿タイプアーカイブ

以下は「レンタル」と言うカスタム投稿タイプのアーカイブページ(archive-rental.php)での出力結果です。WP_Post_Type オブジェクトが取得されます。

object(WP_Post_Type)#4408 (30) {  //WP_Post_Type オブジェクト
  ["name"]=>string(6) "rental"
  ["label"]=>string(12) "レンタル"
  //register_post_type() で指定した(またはデフォルトの)値
  ["labels"]=>object(stdClass)#4413 (31) {  
    ["name"]=>string(12) "レンタル"
    ["singular_name"]=>string(12) "レンタル"
    ["add_new"]=>string(24) "新規レンタル追加"
    ["add_new_item"]=>string(21) "新規投稿を追加"
    ["edit_item"]=>string(21) "レンタルの編集"
    ["new_item"]=>string(12) "新規投稿"
    ["view_item"]=>string(21) "レンタルを表示"
    ["view_items"]=>string(15) "投稿の表示"
    ["search_items"]=>string(21) "レンタルを検索"
    ["not_found"]=>string(48) "レンタルは見つかりませんでした。"
    ["not_found_in_trash"]=>string(54) "ゴミ箱にレンタルはありませんでした。"
    ["parent_item_colon"]=>NULL
    ["all_items"]=>string(12) "レンタル"
    ["archives"]=>string(12) "レンタル"
    ["attributes"]=>string(15) "投稿の属性"
    ["insert_into_item"]=>string(15) "投稿に挿入"
    ["uploaded_to_this_item"]=>string(36) "この投稿へのアップロード"
    ["featured_image"]=>string(24) "アイキャッチ画像"
    ["set_featured_image"]=>string(33) "アイキャッチ画像を設定"
    ["remove_featured_image"]=> string(33) "アイキャッチ画像を削除"
    ["use_featured_image"]=> string(39) "アイキャッチ画像として使用"
    ["filter_items_list"]=>string(30) "投稿リストの絞り込み"
    ["items_list_navigation"]=>string(36) "投稿リストナビゲーション"
    ["items_list"]=>string(15) "投稿リスト"
    ["item_published"]=>string(30) "投稿を公開しました。"
    ["item_published_privately"]=>string(36) "投稿を限定公開しました。"
    ["item_reverted_to_draft"]=> string(39) "投稿を下書きに戻しました。"
    ["item_scheduled"]=>string(30) "投稿を予約しました。"
    ["item_updated"]=>string(30) "投稿を更新しました。"
    ["menu_name"]=> string(12) "レンタル"
    ["name_admin_bar"]=>string(12) "レンタル"
  }
  ["description"]=>string(0) ""
  ["public"]=>bool(true)
  ["hierarchical"]=>bool(false)
  ["exclude_from_search"]=>bool(false)
  ["publicly_queryable"]=>bool(true)
  ["show_ui"]=>bool(true)
  ["show_in_menu"]=>bool(true)
  ["show_in_nav_menus"]=>bool(true)
  ["show_in_admin_bar"]=>bool(true)
  ["menu_position"]=>int(5)
  ["menu_icon"]=>NULL
  ["capability_type"]=>string(4) "post"
  ["map_meta_cap"]=>bool(true)
  ["register_meta_box_cb"]=>NULL
  ["taxonomies"]=>array(2) {
    [0]=>string(10) "rental_cat"
    [1]=>string(10) "rental_tag"
  }
  ["has_archive"]=>bool(true)
  ["query_var"]=>string(6) "rental"
  ["can_export"]=>bool(true)
  ["delete_with_user"]=>NULL
  ["_builtin"]=>bool(false)
  ["_edit_link"]=>string(16) "post.php?post=%d"
  ["cap"]=>object(stdClass)#4410 (15) {
    ["edit_post"]=>string(9) "edit_post"
    ["read_post"]=>string(9) "read_post"
    ["delete_post"]=>string(11) "delete_post"
    ["edit_posts"]=>string(10) "edit_posts"
    ["edit_others_posts"]=>string(17) "edit_others_posts"
    ["publish_posts"]=>string(13) "publish_posts"
    ["read_private_posts"]=>string(18) "read_private_posts"
    ["read"]=>string(4) "read"
    ["delete_posts"]=>string(12) "delete_posts"
    ["delete_private_posts"]=> string(20) "delete_private_posts"
    ["delete_published_posts"]=> string(22) "delete_published_posts"
    ["delete_others_posts"]=>string(19) "delete_others_posts"
    ["edit_private_posts"]=>string(18) "edit_private_posts"
    ["edit_published_posts"]=>string(20) "edit_published_posts"
    ["create_posts"]=>string(10) "edit_posts"
  }
  ["rewrite"]=>array(5) {
    ["slug"]=>string(6) "rental"
    ["with_front"]=>bool(true)
    ["pages"]=>bool(true)
    ["feeds"]=> bool(true)
    ["ep_mask"]=>int(1)
  }
  ["show_in_rest"]=>bool(true)
  ["rest_base"]=>bool(false)
  ["rest_controller_class"]=>bool(false)
  ["hierarchicla"]=>bool(false)
}

ポストタイプオブジェクトのメンバー変数
プロパティ 意  味
name 投稿タイプ名
label 投稿タイプのラベル
description 説明
hierarchical 階層
public 公開するかどうか
rewrite リライトルール
has_archive アーカイブを表示するかどうか
query_var クエリー変数
publicly_queryable フロントエンドで post_type クエリが実行可能かどうか
exclude_from_search 検索対象外にするかどうか
map_meta_cap 内部のデフォルト権限を使用するかどうか???
register_meta_box_cb カスタムフィールドの入力欄を設定するための関数
taxonomies 付属するタクソノミー(配列)
show_ui 管理画面にカスタム投稿タイプの作成や一覧のページを表示するかどうか
menu_position メニュー位置
menu_icon メニューアイコン
can_export カスタム投稿をエクスポート可能かどうか
show_in_nav_menus カスタムメニューに追加可能かどうか
show_in_menu メニューに表示するかどうか
show_in_admin_bar 管理バーに表示するかどうか
delete_with_user
_builtin ビルトインの投稿タイプかどうか
_edit_link この投稿タイプのエントリを編集するリンク。"post.php?post=%d"
capability_type 権限タイプ
cap 権限
["edit_post"]
["read_post"]
["delete_post"]
["edit_posts"]
["edit_others_posts"]
["publish_posts"]
["read_private_posts"]
["read"]
["delete_posts"]
["delete_private_posts"]
["delete_published_posts"]
["delete_others_posts"]
["edit_private_posts"]
["edit_published_posts"]
labels 管理画面のラベル
["name"]
["singular_name"]
["add_new"]
["add_new_item"]
["edit_item"]
["new_item"]
["view_item"]
["search_items"]
["not_found"]
["not_found_in_trash"]
["parent_item_colon"]
["all_items"]
["menu_name"]
["name_admin_bar"]

投稿者アーカイブ

以下は投稿者アーカイブページでの実行結果です。WP_User オブジェクトが取得されます。

object(WP_User)#4543 (8) {  //WP_User オブジェクト
  ["data"]=>
  object(stdClass)#4542 (10) {
    ["ID"]=>string(1) "1"
    ["user_login"]=>string(6) "ログイン名"
    ["user_pass"]=>string(34) "パスワード"
    ["user_nicename"]=>string(6) "ニックネーム"
    ["user_email"]=>string(25) "メールアドレス"
    ["user_url"]=>string(0) ""
    ["user_registered"]=>string(19) "2019-01-03 00:32:33"
    ["user_activation_key"]=>string(0) ""
    ["user_status"]=> string(1) "0"
    ["display_name"]=>string(8) "nickname"
  }
  ["ID"]=>int(1)
  ["caps"]=>array(1) {
    ["administrator"]=>bool(true)
  }
  ["cap_key"]=>string(15) "wp_capabilities"
  ["roles"]=>array(1) {
    [0]=>string(13) "administrator"
  }
  ["allcaps"]=>array(62) {  //権限関連
    ["switch_themes"]=>bool(true)
    ["edit_themes"]=>bool(true)
    ["activate_plugins"]=>bool(true)
    ["edit_plugins"]=>bool(true)
    ["edit_users"]=>bool(true)
    ・・・中略・・・
    ["delete_themes"]=>bool(true)
    ["export"]=>bool(true)
    ["administrator"]=>bool(true)
  }
  ["filter"]=>NULL
  ["site_id":"WP_User":private]=>int(1)
}

投稿タイプの情報やオブジェクトを取得

get_post

投稿 ID で指定した1件の投稿の情報(オブジェクト)を取得します。複数の投稿を読み込む場合は get_posts() を使います。

$output パラメータで戻り値の型を指定できます。$filter パラメータには、取得したレコード内の各フィールドに対する無害化のコンテキストを指定することができます。

投稿 ID を指定しない場合は、現在の投稿が取得されます。

get_post( $id, $output, $filter )

パラメータ
  • $id(整数|オブジェクト):(オプション) 取得したい投稿の ID、または投稿オブジェクト。初期値: null (現在の投稿)。バージョン 3.5 より前は変数に入れて参照渡しする必要がありましたが、今は必要ありません。
  • $output(定数の文字列):(オプション) 戻り値の型示す定数 OBJECT, ARRAY_A, ARRAY_N の何れか(省略時は OBJECT)
    • OBJECT:オブジェクト
    • ARRAY_A:連想配列。(連想配列のキーがオブジェクトのプロパティ名)
    • ARRAY_N:通常の配列
  • $filter(文字列):(オプション) 無害化のコンテキスト(フィルター名)。初期値:'raw'
    • 'raw':数値フィールドの値のみ無害化
    • 'edit':各種フィルターフックで無害化
    • 'db':各種フィルターフックで無害化
    • 'display':各種フィルターフックで無害化
戻り値
$output で指定した形式の投稿のオブジェクト( WP_Post オブジェクト)。投稿情報が見つからない場合は null。
利用可能箇所
どこでも可能

取得した情報のフィールド(オブジェクトのプロパティ)から様々な情報が取得できます。

参照:WP_Post オブジェクト メンバー変数

<?php
$post_7 = get_post( 7 ); 
// 投稿のタイトルを取得
$title = $post_7->post_title;
?>

以下が get_post() のソースです。

function get_post( $post = null, $output = OBJECT, $filter = 'raw' ) {
  if ( empty( $post ) && isset( $GLOBALS['post'] ) ) {
    $post = $GLOBALS['post'];
  }

  if ( $post instanceof WP_Post ) {
    $_post = $post;
  } elseif ( is_object( $post ) ) {
    if ( empty( $post->filter ) ) {
      $_post = sanitize_post( $post, 'raw' );
      $_post = new WP_Post( $_post );
    } elseif ( 'raw' == $post->filter ) {
      $_post = new WP_Post( $post );
    } else {
      $_post = WP_Post::get_instance( $post->ID );
    }
  } else {
    $_post = WP_Post::get_instance( $post );
  }

  if ( ! $_post ) {
    return null;
  }

  $_post = $_post->filter( $filter );

  if ( $output == ARRAY_A ) {
    return $_post->to_array();
  } elseif ( $output == ARRAY_N ) {
    return array_values( $_post->to_array() );
  }

  return $_post;
  }

get_post_type

現在の投稿または指定した投稿の投稿タイプを取得します

get_post_type( $post )

パラメータ
$post(整数|オブジェクト|null):(オプション) 投稿タイプを取得したい投稿の ID または投稿オブジェクト。未指定の場合は現在の投稿が対象。初期値: null
戻り値
投稿タイプ(文字列)。取得できなかった場合は false。

投稿タイプには以下のようなものがあります。

  • 'post' : 投稿
  • 'page' : 固定ページ
  • 'attachment' : 添付ファイル
  • 'revision' : リビジョン
  • 'nav_menu_item' : ナビゲーションメニュー
  • 'カスタム投稿タイプ'

以下はカスタム投稿タイプのループ内で、投稿タイプをクラス属性の値として出力する例です。

get_post_type() にパラメータを指定していないので、現在の投稿の投稿タイプが取得されます。

カスタム投稿タイプの場合は取得される値はカスタム投稿タイプ名(スラッグ)で、register_post_type() で第1パラメータに指定したカスタム投稿タイプ名($post_type)になります。

esc_attr() は属性値に出力する場合のエスケープ処理の関数です。

<p class="<?php echo esc_attr(get_post_type()); ?>">・・・</p>

上記の場合、そのカスタム投稿タイプ名(スラッグ)が「rental」だと以下のように出力されます。

<p class="rental">・・・</p>

投稿タイプが取得できない場合

get_post_type() はパラメータを指定しない場合は自動的に現在の投稿が対象となります。

このため、通常は投稿の個別ページや固定ページの場合は投稿が存在するので、投稿タイプを取得することができます。

フロントページやアーカイブページではループで取得される最初の投稿($post)の投稿タイプが取得されます。

但し、アーカイブページで投稿がない(該当する記事がない)場合は get_post_type() では投稿タイプは取得できません。

カスタムタクソノミーのアーカイブページで投稿が存在しない場合に投稿タイプを取得するには、カスタムタクソノミーの名前からカスタム投稿タイプのスラッグを取得して投稿タイプとすることはできます。

以下のように get_query_var() でタクソノミー名を取得して、get_taxonomy() でタクソノミーオブジェクトを取得し、そのプロパティからスラッグ(投稿タイプ名)を取得します。

$taxonomy = get_query_var( 'taxonomy' );
$post_type = get_taxonomy( $taxonomy )->object_type[0];

カテゴリーは投稿(投稿タイプ:post)に属するので、get_query_var( 'category_name' ) で値が取得できれば、投稿タイプは post と判断しても良いかも知れません(何をするかによると思います)。

投稿者別アーカイブの場合に、投稿がない場合は投稿タイプを特定することは難しいかと思います。

以下は全く実用的ではありませんが、色々なページで投稿タイプを取得する例です。

<?php 
if(get_post_type()){
  $post_type = get_post_type();
}else if(get_query_var( 'taxonomy' )){
  $taxonomy = get_query_var( 'taxonomy' );
  $post_type = get_taxonomy( $taxonomy )->object_type[0];
}else if(get_query_var( 'category_name' )) {
  $post_type = 'post';
}else if(get_query_var( 'author' ) && !get_query_var( 'author_name' )) {
  $post_type = 'unknown: author archive page but no post';
}else {
  $post_type = 'unknown';
}
echo 'possible post_type =  ' . $post_type ; 
 ?>

表示中の記事と同じカスタム投稿タイプの投稿一覧を表示

カスタム投稿タイプの個別ページで、表示中の記事と同じカスタム投稿タイプの投稿一覧を表示する例です。

表示中の記事と同じ投稿タイプの記事を取得するには、WP_Query のサブループで post_type パラメータに同じ投稿タイプを渡します。

あまり問題はないと思われますが、ループの外で記述することを想定しているので get_post_type() のパラメータには表示中の記事のオブジェクトを get_queried_object() で取得して指定しています(この方法は個別ページの場合のみ可能で、アーカイブページではエラーになり使えません)。

またループの中では投稿 ID を確認して、表示中の記事と同じ場合はその項目にはリンクを付けないようにしています。

<?php
$queried_obj = get_queried_object();  //現在クエリされているオブジェクトの取得
$args = array(  //サブループのパラメータ
  'posts_per_page' => 5,  //最新の5件を表示
  'post_type' => get_post_type( $queried_obj ), //表示中の記事と同じ投稿タイプの記事を取得
);
$my_query = new WP_Query( $args );
?>
<?php if($my_query->have_posts()): ?>  //サブループ
<ul>
  <?php while($my_query->have_posts()): $my_query->the_post(); ?>
  <?php if($post->ID !== $queried_obj->ID) : ?>  //投稿IDが異なる場合
  <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
  <?php else: ?>  //投稿IDが同じ場合
  <li><?php the_title(); ?></li>
  <?php endif; ?>
  <?php endwhile; ?>
</ul>
<?php endif; ?>
<?php wp_reset_postdata(); ?>

以下が get_post_type() のソースです。

get_post() で投稿オブジェクトを取得してそのプロパティ(post_type)を返しています。

function get_post_type( $post = null ) {
  if ( $post = get_post( $post ) ) {
    return $post->post_type;
  }

  return false;
}

get_post_type_object

投稿タイプ(を表す)オブジェクトを取得します。

get_post_type_object($post_type)

パラメータ
$post_type(文字列):(必須) 投稿タイプ名:以下のような値を指定します。システムに組み込まれている投稿や固定ページなども指定できます。
  • 'カスタム投稿タイプ名':register_post_type() の $post_type パラメータで指定した値
  • 'post':投稿
  • 'page':固定ページ
  • 'attachment':添付ファイル
  • 'revision':リビジョン
  • 'nav_menu_item':ナビゲーションメニュー
戻り値
パラメータで指定された投稿タイプ情報(オブジェクト)。指定した投稿タイプが見つからなかった場合は null

カスタム投稿タイプのラベルや説明を出力

以下はカスタム投稿タイプの個別ページや一覧ページでそのカスタム投稿タイプのラベルや説明を出力する例です。カスタムタクソノミーの一覧ページでも、そのカスタムタクソノミーが属するカスタム投稿タイプのラベルが出力されます。

get_post_type() で現在の投稿の投稿タイプを取得して get_post_type_object() に渡してカスタム投稿タイプのオブジェクトを取得し、その label をエスケープ処理して出力しています。

<?php 
//カスタム投稿のラベル register_post_type() の label に指定した値
echo esc_html( get_post_type_object( get_post_type() ) -> label );  
//カスタム投稿の説明 register_post_type() の description に指定した値
echo esc_html( get_post_type_object( get_post_type() ) -> description );
?>

前述の例のそれぞれの処理を分けて記述すると以下のようになります。

<?php 
$my_post_type = get_post_type();
$my_post_type_object = get_post_type_object($my_post_type);
$my_cp_label = $my_post_type_object->label;
echo esc_html($my_cp_label);
?>

以下が get_post_type_object() のソースです。

グローバル変数 $wp_post_types を参照してその $post_type キーの値(指定した投稿タイプのオブジェクト)を返しています。

function get_post_type_object( $post_type ) {
  global $wp_post_types;

  if ( ! is_scalar( $post_type ) || empty( $wp_post_types[ $post_type ] ) ) {
    return null;
  }

  return $wp_post_types[ $post_type ];
}

get_post_types

登録済み投稿タイプのオブジェクト(または名前)の配列を取得します。

get_post_types($args, $output, $operator)

パラメータ
  • $args(配列):(オプション) 投稿タイプを絞り込むための引数の配列('キー' => 値)。初期値: array()
  • $output(文字列):(オプション) 戻り値の型を指定。'names'(投稿タイプ名のスラッグ)または 'objects'(WP_Post_Type オブジェクト)。初期値: names
  • $operator(文字列):(オプション) $args で複数の条件を指定する場合の論理演算子。and または or。初期値: and
戻り値(配列)
投稿タイプの名前(スラッグ)またはオブジェクトの配列

$args には以下のような引数が使えます(register_post_type() の第2パラメータの一部と同じ)。

$args の引数
引数のキー 値の型 説明
public 真偽値 true の場合、公開されている投稿タイプが返されます。
show_ui 真偽値 true の場合、管理画面に表示されている投稿タイプが返されます。
hierarchical 真偽値 true の場合、固定ページのような親子関係(階層)がある投稿タイプが返されます。
menu_position 整数 カスタム投稿のメニューの位置の数値。
menu_icon 文字列 カスタム投稿のメニューに表示するアイコンの URL 。
rewrite 真偽値 true の場合、リライト(自動 URL 書き換え)している投稿タイプが返されます。
public_queryable 真偽値 true の場合、post_type のクエリが実行可能な投稿タイプが返されます。
exclude_from_search 真偽値 true の場合、検索対象に除外されている投稿タイプが返されます。
query_var 真偽値|文字列 この投稿に使用する query_var キーの名前または真偽値。
show_in_rest 真偽値 true の場合、REST API を有効にしている投稿タイプが返されます。
_builtin 真偽値 true の場合 WordPress のデフォルトの投稿タイプが返され、false の場合はカスタム投稿タイプのみが返されます。

以下は公開されている全てのカスタム投稿タイプの一覧ページへのリンクを出力する例です。

$post_types はカスタム投稿タイプ名(スラッグ)の配列になるので、foreach で1つずつ処理します。

get_post_type_archive_link() はパラメータに投稿タイプ名(スラッグ)を指定すると投稿タイプのアーカイブページへのリンクを返します。

get_post_type_object() でパラメータに指定した投稿タイプのオブジェクトを取得してそのラベルを出力します。

<?php
$args = array(
   'public'   => true, //公開されている投稿タイプ
   '_builtin' => false //カスタム投稿タイプのみを取得
);

$output = 'names'; // 戻り値を投稿タイプ名に
$operator = 'and'; // $args の条件を and で(論理演算子)

$post_types = get_post_types( $args, $output, $operator ); 

if($post_types) {
  echo "<ul>\n";
  foreach ( $post_types  as $post_type ) {
    echo '<li><a href="' . get_post_type_archive_link($post_type) . '">'
    . esc_html(get_post_type_object($post_type)->label) . "</a></li>\n";
  }
  echo '</ul>';
}

?>

前述の例の場合、パラメータの $args public' => true と $output 及び $operator はデフォルトの値を指定しているので省略することができ、以下のように記述することができます。

以下では、出力にカスタム投稿タイプの description の値も出力しています。

<?php
$post_types = get_post_types( array('_builtin' => false) ); 

if($post_types) {
  echo "<ul>\n";
  foreach ( $post_types  as $post_type ) {
    echo '<li><a href="' . get_post_type_archive_link($post_type) . '">'
      . esc_html(get_post_type_object($post_type)->label) . '</a><p>'
      . esc_html(get_post_type_object($post_type)->description) ."</p></li>\n";
  }
  echo '</ul>';
}

?>

以下が get_post_types() のソースです。

function get_post_types( $args = array(), $output = 'names', $operator = 'and' ) {
  global $wp_post_types;

  $field = ( 'names' == $output ) ? 'name' : false;

  return wp_filter_object_list( $wp_post_types, $args, $operator, $field );
}

get_post_type_archive_link

指定した投稿タイプのアーカイブページのリンクを返します。

get_post_type_archive_link( $post_type )

パラメータ
$post_type(文字列):(必須) 投稿タイプ名
戻り値
指定した投稿タイプのアーカイブページへのリンク。指定した投稿タイプが存在しない場合やその投稿タイプにアーカイブがない場合は false。

以下は rental と言う名前のカスタム投稿タイプのアーカイブページへのリンクを出力する例です。

この場合、パラメータに指定するカスタムタイプ投稿名は register_post_type() の第1パラメータの値です。

<a href="<?php echo get_post_type_archive_link( 'rental' ); ?>">Rental</a>

以下が get_post_type_archive_link() のソースです。

パラメータに 'post' が指定された場合は get_option() で管理画面「設定」→「表示設定」の「ホームページの表示」を確認してホームページの URL を返しています。

function get_post_type_archive_link( $post_type ) {
  global $wp_rewrite;
  if ( ! $post_type_obj = get_post_type_object( $post_type ) ) {
    return false;
  }

  if ( 'post' === $post_type ) {
    $show_on_front  = get_option( 'show_on_front' );
    $page_for_posts = get_option( 'page_for_posts' );

    if ( 'page' == $show_on_front && $page_for_posts ) {
      $link = get_permalink( $page_for_posts );
    } else {
      $link = get_home_url();
    }
    /** This filter is documented in wp-includes/link-template.php */
    return apply_filters( 'post_type_archive_link', $link, $post_type );
  }

  if ( ! $post_type_obj->has_archive ) {
    return false;
  }

  if ( get_option( 'permalink_structure' ) && is_array( $post_type_obj->rewrite ) ) {
    $struct = ( true === $post_type_obj->has_archive ) ? $post_type_obj->rewrite['slug'] : $post_type_obj->has_archive;
    if ( $post_type_obj->rewrite['with_front'] ) {
      $struct = $wp_rewrite->front . $struct;
    } else {
      $struct = $wp_rewrite->root . $struct;
    }
    $link = home_url( user_trailingslashit( $struct, 'post_type_archive' ) );
  } else {
      $link = home_url( '?post_type=' . $post_type );
  }

  /**
   * Filters the post type archive permalink.
   * @since 3.1.0
   * @param string $link      The post type archive permalink.
   * @param string $post_type Post type name.
   */
  return apply_filters( 'post_type_archive_link', $link, $post_type );
}