WordPressで、スラッグ(slug)からページや投稿を取得する方法

最終更新:2023-08-05 by Joe

WordPressのページを、スラッグ(slug)を使ってスラッグをマッチさせ、投稿や固定ページを取得する方法です。

念のため、最初に確認しておきますが、WordPressにおける「スラッグ(slug)」とは、URLのパスのスラッシュで囲まれた文字列の事です。

WordPress投稿においては、その投稿に固有の値となり、投稿のパーマリンクなどに使われることがあります。ただし、WordPressnいおいて、パーマリンク形式は簡単にカスタマイズできますので、必ずしも投稿のスラッグが使われているとは限りません。

データベースの、投稿データである「post」 テーブル内には、’post_name’ というフィールドがあり、そこに必ず文字列が保存されています。この値がほぼ「投稿のスラッグ」と同値です。

スラッグから投稿やページを取得する関数

WordPressコアコードには、直接スラッグから投稿を取得する関数は存在しないようですので、自作する必要があります。

下記に、関数にしました。下記は投稿タイプ「page」を取得する関数です。

/**
 * Get a page object by slug.
 * https://codex.wordpress.org/Template_Tags/get_posts
 */
function wwwc_get_page_by_slug( $slug ) {
  $pages = get_posts(
      array(
        'post_type'      => 'page',
        'name'           => $slug,
        'posts_per_page' => 1,
        'no_found_rows'  => true,
      )
  );
  return $pages ? $pages[0] : false;
}

get_posts() 関数は、投稿オブジェクトの「配列」を返してくるので、配列内の必要な最初の要素だけを参照してやります。見つからなければ空の配列です。

no_found_rows はそれほど重要ではありませんが、このフラグがあれば、SQLクエリで found_rows を呼び出すのを控えます(その分、わずかにパフォーマンスに優れます)この関数では1つの投稿をクエリしているだけですので、カウントは不要です。

注意:同じスラッグをもつ投稿が存在する場合がある

管理画面でスラッグを書き換えようとしても、同じスラッグを防止する機能がありますが、例外があります。

同じスラッグが発生するケース:

  • 投稿タイプが異なる場合
  • 投稿の「親」が異なる

投稿タイプに関しては、上記のpost_type’ で指定していますので、省けます。

親が異なる場合は、複数の投稿が帰ってきますので、クエリする前・もしくはその後で、適宜必要なものにフィルターする必要があります。

post_parent を投稿 IDで1つ指定する例です。

function wwwc_get_page_by_slug( $slug, $parent_id = false ) {
  $args = array(
    'post_type'      => 'page',
    'name'           => $slug,
    'posts_per_page' => 1,
    'no_found_rows'  => true,
  );

  if ( $parent ) {
    $args['post_parent'] => $parent_id
  }

  $pages = get_posts( $args );
  
  return $pages ? $pages[0] : false;
}

get_posts() 関数は、瀧にわたる引数をしていできますので、詳しくはマニュアルを参照してみてください。

投稿をクエリして取得する時の注意

WordPressおけるよくある間違いが「query_posts()」を使ってしまう例です。query_posts() 関数はメインクエリを操作する関数ですので、今回のような、追加的なカスタムクエリに使うべきものではありません。

query_posts() を呼び出すと、メインループのためのグローバル変数 $wp_query を書き換えてしまいますので中止います。これに関しては、マニュアルやソースコードがわかりやすいですので、個々での説明は割愛します。

通常のテーマ実装では、特別な意図がない限り、query_postsを使う事はほぼありません。

WordPressの「スラッグ」について

スラッグは、ワードプレスの postテーブル(投稿を格納するテーブルです。)にカラムとして格納されています。1投稿(ページ)あたり1スラッグ、格納する場所が最初から用意されているってことですね。

postテーブルのカラム、貼っておきます。「post_name」ってのがそれに当たります。

スラッグで投稿をクエリする、というのは、実際は、post_name でマッチする投稿をクエリする、というそれだけの処理となります。

mysql> show columns from wp_posts;
+-----------------------+---------------------+------+-----+---------------------+----------------+
| Field                 | Type                | Null | Key | Default             | Extra          |
+-----------------------+---------------------+------+-----+---------------------+----------------+
| ID                    | bigint(20) unsigned | NO   | PRI | NULL                | auto_increment |
| post_author           | bigint(20) unsigned | NO   | MUL | 0                   |                |
| post_date             | datetime            | NO   |     | 0000-00-00 00:00:00 |                |
| post_date_gmt         | datetime            | NO   |     | 0000-00-00 00:00:00 |                |
| post_content          | longtext            | NO   |     | NULL                |                |
| post_title            | text                | NO   |     | NULL                |                |
| post_excerpt          | text                | NO   |     | NULL                |                |
| post_status           | varchar(20)         | NO   |     | publish             |                |
| comment_status        | varchar(20)         | NO   |     | open                |                |
| ping_status           | varchar(20)         | NO   |     | open                |                |
| post_password         | varchar(20)         | NO   |     |                     |                |
| post_name             | varchar(200)        | NO   | MUL |                     |                |
| to_ping               | text                | NO   |     | NULL                |                |
| pinged                | text                | NO   |     | NULL                |                |
| post_modified         | datetime            | NO   |     | 0000-00-00 00:00:00 |                |
| post_modified_gmt     | datetime            | NO   |     | 0000-00-00 00:00:00 |                |
| post_content_filtered | longtext            | NO   |     | NULL                |                |
| post_parent           | bigint(20) unsigned | NO   | MUL | 0                   |                |
| guid                  | varchar(255)        | NO   |     |                     |                |
| menu_order            | int(11)             | NO   |     | 0                   |                |
| post_type             | varchar(20)         | NO   | MUL | post                |                |
| post_mime_type        | varchar(100)        | NO   |     |                     |                |
| comment_count         | bigint(20)          | NO   |     | 0                   |                |
+-----------------------+---------------------+------+-----+---------------------+----------------+

スラッグとページ取得に関する参考リンク