MySQLに以下のテーブルがあるとします。
テーブル名 sample_table
フィールド id
title
text
このテーブルのレコードを、
http://www.hogehoge.com/○○○.html
のようにHTMLファイル(あるいはPHPでも)でパブリッシュするような仕組みが欲しいです。
上記URLの○○○にはidフィールドの値が入るようなイメージで、HTMLファイルの中身はtextフィールドです。
http://www.hogehoge.com/aaa.php?ID=○○○
上記のようなURLではなく、あくまで最初のような形です。
このような仕組みは可能なのでしょうか?
新しくレコードが追加された場合も自動的にパブリッシュされ、レコードが削除された場合はファイルも削除されると完璧です。
パブリッシュ形式はいわゆる静的なURLならばHTMLでもPHPでも構いません。
皆様よろしくお願い致します。
まず、結論からいいます。
tokyosmashさんが、お使いのMovableTypeで使用している.htaccessのRewriteEngine onの直後に、以下3行をコピーして貼り付けて下さい。
RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)\.html$ aaa.php?ID=$1 [L]
以下、理由を知りたい場合は、読んでください。
http://www.net-newbie.com/trans/mod_rewrite.html
を参考にしましたが、よくわからないところがありました。
以下は、実験を繰り返して得た結論です。説明が正確でない部分があると思いますが、ご容赦ください。
詳しい書き方は上記リンクに譲るとして、RewriteCondディレクティブとRewriteRuleディレクティブ、そして、RewriteRuleディレクティブの第三引数、[L]フラグの関係について書きます。
RewriteCondや、[L]フラグがないと文法的に誤りというわけではありませんが、以下は、それがあるのを前提に説明します。RewriteCondから、RewriteRuleの[L]までが一つのまとまりと考えると分かりやすいです。今回の説明の中では、このまとまりを「基本セット」と言うことにします。基本セットは、いくつあっても構いません。ファイルの上に書いたものから優先的に適用されます。
次の2行を書くと、実際にあるファイル名やディレクトリ名のときは、RewriteRuleを適用しません。 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRuleディレクティブの第三引数に、[L]フラグを書くと、マッチした場合は、それ以降の基本セットを無視します。
以上は、マニュアルをよく読むとわかります。
以下が、マニュアルでは分かりにくい部分です。
RewriteCondの効力は、それが属する基本セット内だけにしか及びません。同じ効力を別の基本セット内でも使いたい場合は、その基本セット内でRewriteCondを書く必要があります。 [L]フラグつきのRewriteRuleを連続して書いても、二つの基本セットとは見なされません。一つ目の[L]は無視されます。つまり、一つ目のRewriteRuleにマッチしても、さらに、重複して次のRewriteRuleが適用されます。 一つ目のRewriteRuleにマッチしたら、次のRewriteRuleを無視したい場合は、この2つのRewriteRuleの間に、RewriteCondを入れて下さい。これで、2つのことなる基本セットとみなされます。
Apache なら mod_rewrite でそう見せかければよい。
RewriteEngine On RewriteRule ^/([a-zA-Z0-9]+\.html /aaa.php?ID=$1 [L]
で、実際の処理は aaa.php に記述。
なるほどこれは勉強になります!
SEO対策にも使えますね。
ただこのままだと既存のHTMLファイルへのアクセスが全部飛ばされちゃいますよね。ディレクトリを別にすれば解決しますが。
実は試してみたのですが、うまくいきません。
参考URLとb-windさんの書き方が微妙に違うのですが、ちょっと混乱しています。
恐らく参考URLの方に記述ミスがあるとは思うのですが。。
他の方法があれば、よろしくお願いします。回答はまだまだ受け付けています。実際にパブリッシュする方法があれば教えてください。
RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)\.html$ aaa.php?ID=$1 [L]
これで、既存のHTMLファイルへのアクセスも大丈夫です。
お試しください。
昨日から度々お世話になっています。
うーんうまくいきません。
URLが存在しない、ってなります。
.htaccessをテキストファイルで編集する際に
\ が ¥ に変換されてしまうのですがそれは問題ないのでしょうか?
それでは、私の行った実験と同じようにして頂けますか?
※下記の.htaccessとaaa.phpを同じディレクトリに置いて下さい。
.htaccessの中身(先の回答と同じものです。)
\ が ¥ に変換されてしまうのは、OKです。
RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)\.html$ aaa.php?ID=$1 [L]
// aaa.phpの中身
<?php echo "GET:"; print_r($_GET); ?>
実験1
ブラウザのアドレスに次のように入力
もちろん、www.hogehoge.comはご自分の環境にあわせて変更して下さい。
http://www.hogehoge.com/aaa.php?ID=bbb
次のようにブラウザに表示されます。
もし、この段階でダメならば、.htaccessの問題ではないですよね。
GET:Array ( [ID] => bbb )
実験2
ブラウザのアドレスに次のように入力
www.hogehoge.comはご自分の環境にあわせて変更して下さい。
注意1:ここで、最後に「html/」などと「/」をつけてはダメですよ。
注意2:htmlであって、htmはダメ
http://www.hogehoge.com/ddd.html
次のようにブラウザに表示されます。
GET:Array ( [ID] => ddd )
以上どうでしょうか?
※質問終了前でも、この質問・回答へのコメントを書けるようにして頂けると、ありがたいです。今から変えるのは無理でしょうか
ご丁寧にありがとうございます。
早速実験してみました。
1は出来ました。
2で500エラーになってしまいます。
実はサーバーはXREA(有料)なのですが、これが原因でしょうか?
>質問終了前でも、この質問・回答へのコメントを書けるよう
このような設定が出来るのですね。最近はてなを始めたもので知りませんでした。
まず、結論からいいます。
tokyosmashさんが、お使いのMovableTypeで使用している.htaccessのRewriteEngine onの直後に、以下3行をコピーして貼り付けて下さい。
RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)\.html$ aaa.php?ID=$1 [L]
以下、理由を知りたい場合は、読んでください。
http://www.net-newbie.com/trans/mod_rewrite.html
を参考にしましたが、よくわからないところがありました。
以下は、実験を繰り返して得た結論です。説明が正確でない部分があると思いますが、ご容赦ください。
詳しい書き方は上記リンクに譲るとして、RewriteCondディレクティブとRewriteRuleディレクティブ、そして、RewriteRuleディレクティブの第三引数、[L]フラグの関係について書きます。
RewriteCondや、[L]フラグがないと文法的に誤りというわけではありませんが、以下は、それがあるのを前提に説明します。RewriteCondから、RewriteRuleの[L]までが一つのまとまりと考えると分かりやすいです。今回の説明の中では、このまとまりを「基本セット」と言うことにします。基本セットは、いくつあっても構いません。ファイルの上に書いたものから優先的に適用されます。
次の2行を書くと、実際にあるファイル名やディレクトリ名のときは、RewriteRuleを適用しません。 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRuleディレクティブの第三引数に、[L]フラグを書くと、マッチした場合は、それ以降の基本セットを無視します。
以上は、マニュアルをよく読むとわかります。
以下が、マニュアルでは分かりにくい部分です。
RewriteCondの効力は、それが属する基本セット内だけにしか及びません。同じ効力を別の基本セット内でも使いたい場合は、その基本セット内でRewriteCondを書く必要があります。 [L]フラグつきのRewriteRuleを連続して書いても、二つの基本セットとは見なされません。一つ目の[L]は無視されます。つまり、一つ目のRewriteRuleにマッチしても、さらに、重複して次のRewriteRuleが適用されます。 一つ目のRewriteRuleにマッチしたら、次のRewriteRuleを無視したい場合は、この2つのRewriteRuleの間に、RewriteCondを入れて下さい。これで、2つのことなる基本セットとみなされます。
実際に実行してみましたが、hogehoge.com/aaa.php?ID=12 で飛ばされる先のURLは正常に表示されました。
つまり hogehoge.com/12.html
にアクセスすると正常に表示されたという事です。
しかし、従来からある通常のページが表示されません。
つまり hogehoge.com/company.html のようなページです。
表示されないといっても404や500エラーではなく、hogehoge.com/aaa.php?ID=companyにアクセスした状態になります。
真っ白な画面です。
少し考えてみました。
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
この2行を書くことで「実際にあるページは通常通り表示される」との事ですが、ほぼ全てのページをダイナミックパブリッシングしているので、hogehoge.com/company.htmlのようなページも「実際には存在しない」と見なされているのではないでしょうか。
index.htmlのみは静的HTMLで書き出しているのですが、こちらは正常に表示されます。
そこで一つ思いつきました。
aaa.php?ID=$1で飛ばしたい先のURLを.htmlではなくて.phpにして、
RewriteRule ^(.*)\.php$ aaa.php?ID=$1
にすればいいのではないでしょうか。
RewriteRule ^(.*)\.html$ aaa.php?ID=$1
だと通常のページ(全てhtmlで書き出されています)を拾ってしまうので。
これでうまくいきました。
どうでしょうか?
実際に実行してみましたが、hogehoge.com/aaa.php?ID=12 で飛ばされる先のURLは正常に表示されました。
つまり hogehoge.com/12.html
にアクセスすると正常に表示されたという事です。
しかし、従来からある通常のページが表示されません。
つまり hogehoge.com/company.html のようなページです。
表示されないといっても404や500エラーではなく、hogehoge.com/aaa.php?ID=companyにアクセスした状態になります。
真っ白な画面です。
少し考えてみました。
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
この2行を書くことで「実際にあるページは通常通り表示される」との事ですが、ほぼ全てのページをダイナミックパブリッシングしているので、hogehoge.com/company.htmlのようなページも「実際には存在しない」と見なされているのではないでしょうか。
index.htmlのみは静的HTMLで書き出しているのですが、こちらは正常に表示されます。
そこで一つ思いつきました。
aaa.php?ID=$1で飛ばしたい先のURLを.htmlではなくて.phpにして、
RewriteRule ^(.*)\.php$ aaa.php?ID=$1
にすればいいのではないでしょうか。
RewriteRule ^(.*)\.html$ aaa.php?ID=$1
だと通常のページ(全てhtmlで書き出されています)を拾ってしまうので。
これでうまくいきました。
どうでしょうか?