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 | | +-----------------------+---------------------+------+-----+---------------------+----------------+