WordPressの.htaccessにデフォルトで記載されているmod_rewriteについて

WordPressの.htaccessにデフォルトで記載されているmod_rewriteについてまとめてみました。

mod_rewriteとは?

mod_rewriteとは、何かご存知でしょうか?
これは、Apacheというhttpサーバで利用されいてるモジュールと言われるもので、URLの書き換え・リダイレクト処理を行なってくれるものです。
主に「.htaccess」というファイルに任意の処理を記述して使用します。

mod_rewriteですが、使ってはいるけど内容はよくわからない方も多いのでは無いでしょうか?
実際にWordPressのパーマリンク設定で利用しているmod_rewrite のコードを参考に説明を行なっていきます。
まずは、利用しているコードを確認してみましょう。

WordPressのパーマリンク設定で利用しているmod_rewrite

1 <IfModule mod_rewrite.c>
2 RewriteEngine On
3 RewriteBase /
4 RewriteCond %{REQUEST_FILENAME} !-f
5 RewriteCond %{REQUEST_FILENAME} !-d
6 RewriteRule . /index.php [L]
7 </IfModule>

WordPressのサイトを運用している方は、ほとんどの方が見たことがあるのではないかと思うくらいおなじみのやつですね。
実際にWordPressを運用している方でも、この記述を理解している方は半分くらいじゃないかと個人的に予想しています。
私も、はじめの内は全くわからずに利用をしておりました。

WordPressを初めて利用した際に当時WEBの初心者であった私は、とても驚きました。
どうして、このコードを記載するだけでパーマリンクを自由に設定ができるのか。
どうして、ピンポイントに存在しないファイルだけ静的なファイルが読み込まれるのか。
どうして、存在しないページでもちゃんとWordPressのエラーページが表示されるのか。
そのカラクリが不思議で仕方がありませんでした。
今回WordPressを選択した理由は、私と同様に不思議に感じていた方もいるのでは無いかという事と、様々な記述がありステップアップにも調度良いという事。WordPress自体が広く普及している点があります。

一行目から順にどういった意味を持つコードなのか確認していきましょう。

1 <IfModule mod_rewrite.c>

何やらHTMLタグのような形で記述されていますね。
最後の行も見てみると、今度はHTMLの閉じタグのような形で記載されています。
これは利用環境でmod_rewriteが利用できるかどうかを確認しています。
もし利用できない場合は、このHTMLタグのような形で挟まれている行のコードが一切適用されなくなります。

mod_rewriteが利用できない環境でmod_ rewriteのコードを記述するとエラーが発生してしまいます。ですから、このようにモジュールが利用できるか確認を行なってから実行してくださいという記述をします。

1 RewriteEngine On

これはmod_rewriteの機能を有効化するという記述になります。
Offと記述すれば無効化します。非常に簡単です。

1 RewriteBase /

これはRewrite処理後にベースとなるURLの指定しています。
この記述がない場合は、htaccessを設置しているディレクトリが自動的に選択されますが、これは後述するRewriteRuleを相対パスで記述した場合にのみ適用されます。
特に理由がない場合は、「RewriteBase /」と記述しておく事をオススメします。
この場合だと、どのディレクトリに設置を行った場合でも必ずドキュメントルートからのパスになりますので、わかりやすくなります。

1 RewriteCond %{REQUEST_FILENAME} !-f

ここから、いよいよRewrite処理を記述している部分となります。
RewriteCondではルールの定義を行っています。
Rewrite処理を設定する上で欠かせないポイントなので、mod_rewriteを使う上で特に重要です。

普段、プログラムを普段やられている方はmod_rewriteで使用するif文だと思って貰えればイメージがしやすいと思います。

RewriteCondの次に記述されいている部分「%{REQUEST_FILENAME}」というものが、「!-f」という条件を満たしていれば真となります。
if文で記述してみると下記の様になります。

1 if(%{REQUEST_FILENAME} != -f)
2 {
3     
4 }

まず前方の%{REQUEST_FILENAME}から確認して行きます。
これは変数です。この変数というものには、自分で好きな文字列を入れるものと、サーバーが事前に準備を行なってくれる環境変数というものがあります。
今回使用されているREQUEST_FILENAMEとは環境変数と呼ばれる変数の一部で、このREQUEST_FILENAME以外にも様々なものがあります。
例えばですが、SSL通信かどうかを判断するために利用されるHTTPSや、特定のIPアドレスからアクセスされた場合に参照先を変更するために利用するREMOTE_ADDR等があります。
今回は2つのみ挙げさせて頂きましたが、これ以外にもたくさんの環境変数が存在します。

環境変数の一例

環境変数名 内容
HTTP_USER_AGENT ユーザのブラウザや端末情報を取得することができます。
携帯サイトやスマホサイトなどへの振分の際に利用されます。
HTTP_REFERER 前にいたページのURL情報を取得出来ます。
特定のページからの導線のみ許可したい場合などに利用します。
HTTP_HOST 閲覧しているサイトのドメインです。
主にRewriteRuleなどに使用します。
REMOTE_ADDR ユーザのIPアドレスの取得を行います。
特定のIPのみに特別な処理をしたい場合などに使用します。
HTTPS on|offでSSL通信の有無を判定できます。
SERVER_PORT HTTPSが上手く利用できない場合などに使用します。

このような変数を利用して、様々なルールを作ることができます。
PHPが利用できるサーバーであれば、var_dump($_SERVER)やphpinfo()という関数を利用して環境変数にどのような値が変数に入っているのか確認も可能です。

次に後方部分の!-fについてですが、こちらは条件の記述です。
!-fには2つの条件が含まれており、「!」と「-f」に分割することが出来ます。
まず「-f」はモジュールで準備をしてくれている判定ルールです。これは、前方に指定されていた変数、今回の場合は%{REQUEST_FILENAME}に入っている物がファイルであるかどうかを判定してくれます。

ファイルの場合は、真。ファイル以外の場合は、偽を返します。
分割されたもう一つの「!」は否定です。
結果を逆転させるもので、真と判定されたものは偽となり、偽と判定されたものは真となります。ですから今回の「!-f」の場合はファイル以外の場合は、真を。ファイルの場合は偽を返します。

1 RewriteCond %{REQUEST_FILENAME} !-d

また先ほどと同じような記述がされていますが、条件の部分のみ変更されています。
「-d」と記述されていますが、これはディレクトリかどうかの検証を行います。
%{REQUEST_FILENAME}がディレクトリの場合は真を、それ以外の場合は偽を返しますが、先ほどと同様に「!」がついていますので、結果は逆になります。

RewriteCondが2回続きました。
このように複数回RewriteCondが続いた場合は、全てのRewriteCondで真となる必要があります。偽が1つでもあるとRewrite処理の対象から外れてしまいます。

また、「-d」「-f」などモジュールで準備されている判定ルールですが、もちろんこの2つ以外にもいつくかあります。ただ、利用される部分も少ないため今回の説明を割愛させて頂きます。

1 RewriteRule . /index.php [L]

これは実際にURLの書き換えを行う部分です。
上記はURLが「.(ドット)」であれば「/index.php」を参照するという命令です。
「.(ドット)」の部分が条件となり、ドットはどのような条件でも適用するという条件になります。
「/index.php」はどのように書き換えを行うか記述しており、今回は/index.phpに書き換えを行なっています。
したがって今回の場合は、「すべてのリクエストは/index.phpに書き換えられる」ということになります。

そして記述に一番最後に「[L]」という記述がありますが、これはLastという意味で「このルールが適用されたら、この記述以降の他のルールは適用しません。」という命令です。
これはフラグと言われるもので、RewriteCondにも利用できますし、フラグ自体もL以外にもたくさんあります。
その中でもよく使うものをご紹介します。
[NC]:no case:大文字と小文字を区別しなくなります。

1 RewriteCond %{HTTP_REFERER} example.com [NC]

この場合は、%{HTTP_REFERER}が「Example.com」でも「EXAMPLE.COM」でも真となります。

[R]:redirect:これは書き換え後のURLにリダイレクトを行うことができます。
R=301等の記述をすることでリダイレクトパラメータを使用することもできます。

1 RewriteCond %{HTTP_HOST} ^example\.com
2 RewriteRule (.*) http://www.example.com/$1 [R=301,L]

というような記述をすると、www付きのアドレスにリダイレクトパラメータ付きでリダイレクトさせることが可能です。
また上記のサンプルコードのように[R=301,L]と,(カンマ)で区切ることにより複数のフラグを設定することも可能です。
このリダイレクトの記述がない場合は、リダイレクトは行わず内部的にURLの書き換えだけを行うことになります。

以上が、WordPressで利用しているmod_rewriteの全てです。

改めてコードを見なおしてみましょう。

1 <IfModule mod_rewrite.c>
2 RewriteEngine On
3 RewriteBase /
4 RewriteCond %{REQUEST_FILENAME} !-f
5 RewriteCond %{REQUEST_FILENAME} !-d
6 RewriteRule . /index.php [L]
7 </IfModule>

この内容は、

  • mod_rewriteモジュールを使用出来る。
  • ファイルが存在しない。
  • ディレクトリが存在しない。

という上記にあるすべての条件に当てはまるリクエストは、すべて「/index.php」を参照して下さい。

ということになります。

プログラマよりの内容が多く敢えて触れる必要がないので、スルーしてしまいがちですが、知っておくとWordPressのカスタマイズに活きてきます。

WordPressでindex.htmlへのアクセスされた場合の404を改善!.htaccessによるリダイレクト

元はHTMLで出来ていたサイトをWordPressにした場合、index.htmlなどのGoogleインデックスが残ってしまい、SearchConsoleで『見つかりませんでした 』とクロールエラーが出てしまいました・・・

やはり、「index.html」へのアクセスが、「404 – Page Not Found」はちょっと寂しいですし。

その為、htaccessでindex.htmlなしに統一しクロールエラーを改善する事にしました
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html?$ / [R=301,L]
RewriteRule ^default\.html?$ / [R=301,L]
RewriteCond %{REQUEST_FILENAME} !\.(html?|xml|xsl|js|css|jpe?g|png|gif|ico)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

これでスッキリ統一されてSEO的にも改善されそうです

ちなみにWordPress使っていない場合や404が出てない場合でも統一した方がSEO的によくなります

通常のサイトでindex.html(またはindex.htm)のあり、なしを統一する方法

「index.html」のあり、なしとはどういうことかというと、

http://www.club-s-group.com/index.html
http://www.club-s-group.com/

この2つのアドレスは、
wwwありの(http://www.club-s-group.com/)、wwwなしの(http://club-s-group.com/)の考えと同じように
index.htmlがあり、なしも
別のページ」だと検索ロボットは判断しています。

リンクが分散されますので統一が必要です。

ホームページを見るユーザー(お客様)視点では
アドレスは短く分かりやすいのがいいので
index.htmlなしで統一するのをお勧めします。

今回も.htaccessで301リダイレクトを使い統一する方法です。

「.htaccess」ファイルを使用します。
テキストエディタ(メモ帳など)に、以下の内容を記述し保存してください。

ファイル名は、「1.htaccess.txt」として保存。
(“1”の部分はお好きな文字でOKです。)

index.htmlなしに統一

RewriteEngine on
RewriteCond %{THE_REQUEST} ^.*/index.html
RewriteRule ^(.*)index.html$ http://www.club-s-group.com/$1 [R=301,L]

これで分散されていた評価がまとまりますので、無駄なくSEOの強化が行えます

WordPressのページネーションのサーチコンソール重複対策について

ページネーションされても2ページ目以降のタイトルやらディスクリプションはそのままなのでサーチコンソールで重複をしてきされてしまいます

WordPressのhomeやカテゴリページって、記事が増えていくと勝手にページを分割してくれるじゃないですか。
たとえば以下の様な形になります

http://asc-cl.jp/blog/

http://asc-cl.jp/blog/page/2/

 

多くのテーマでは、特に何も設定しない限り、同一のタイトル・メタディスクリプションで2ページ目以降が生成されます。
まぁ大抵の場合、人間が見れば「あーこれって続きの一覧ページなんだなぁ」と理解できますが、Googleのロボットはどんなに進化しても所詮ロボットなので、しっかりと伝えてあげる必要があるのです。

やりたいこと

1.タイトルやらディスクリプションやらに「このページは2ページ目ですよ」と伝わる表記を入れたい。
2.Googleのロボットに「このページには前のページ(または次のページ)があるよ」と伝えたい。

以上の2点になります。
1.は普通にタイトルやディスクリプションなどに「2ページ目|おれだよ!!!」といったように「◯ページ目」の文字を加える作業です。

また、2.に関しては、rel=”next”とrel=”prev”というタグを使用し、Googleに分割されたページの構成を伝えるものになります。

具体的な手順

タイトルなどに「◯ページ目」を加える

当ブログでは、タイトルタグとメタディスクリプションに「◯ページ目|」の文字を加えています。

タイトルタグを例にとって説明します。
header.php等のtitleタグを管理しているテンプレートに下記の記述を埋め込んで下さい。

<?php if($paged !=0){echo $paged."ページ目|";} ?>

 

if($paged !=1)
の部分は1ページ目には表示させないという記述部分なので、
1ページ目にも表示させる場合は

1
<?php if($paged){echo $paged."ページ目";} ?>

でOK

とのことなのですが、0ページ目も出てしまいますので、0ページ目に表示させないように

$paged !=1

$paged !=0

に変更して実装しています。

普通に存在している1ページ目が0ページ目としてカウントされている原因は意味不明なのですが、表示がおかしい場合は自己責任でいじってみてください。

rel=nextとrel=prevの実装

下記のような要件で実装したいと思いました。

  • homeページ、categoryページ、searchページなどの複数ページに分割されるページに実装
  • 記事ページ等で前の投稿、次の投稿には付けたくない(別に分割されているわけではないので)

どうやら、WordPressが自動でrel=nextやrel=prevを加えてくれるケースもあるようなのですが(テーマによって出力されるかどうかは違う)、その際、条件2つ目のように記事ページにも勝手に出力されてしまうそうです。

これは明らかにGoogleの意図した使用方法とは異なるはずなので、functions.phpに以下の記述を加え、wp_headでrel=nextやrel=prevを自動的に出力させないようにします。

1
2
3
4
5
6
<?php
remove_action('wp_head','index_rel_link');
remove_action('wp_head','parent_post_rel_link');
remove_action('wp_head','start_post_rel_link');
remove_action('wp_head','adjacent_posts_rel_link_wp_head');
?>

 

そして、肝心な分割されるページにrel=prev、rel=nextを加えるためには、おなじみifを使った条件分岐タグで実装します。
header.php内に下記の記述を追加して下さい。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php if(!is_single()|| !is_page()) { ?>
<?php
global $paged, $wp_query;
if ( !$max_page )
$max_page = $wp_query->max_num_pages;
if ( !$paged )
$paged = 1;
$nextpage = intval($paged) + 1;
if ( null === $label )
$label = __( 'Next Page &raquo;' );
if ( !is_singular() && ( $nextpage <= $max_page ) )
{
?>
<link rel="next" href="<?php echo next_posts( $max_page, false ); ?>" />
<?php     
}
global $paged;
if ( null === $label )
$label = __( '&laquo; Previous Page' );
if ( !is_singular() && $paged > 1  )
{
?>
<link rel="prev" href="<?php echo previous_posts( false ); ?>" />
<?php     
}
?>
<?php } ?>

1行目の

<?php if(!is_single()|| !is_page()) { ?>

は、記事ページと固定ページ以外の全てのページに加えるための記述です。
ifの中身で「複数ページにまたがっているかどうか」という条件があるので、必要ないっちゃ必要ない記述なのですが、念の為加えています。