RewriteRule が分かりません

「まったく何も分からない・・・」そんなユーザーさんの為のフォーラムです。どんなご質問でもお気軽にどうぞ。
返信
luis
アクティブユーザー
記事: 20
登録日時: 2007年1月08日(月) 17:35

RewriteRule が分かりません

投稿記事 by luis » 2007年9月12日(水) 20:46

お世話になります。

.htaccess を使っていますが、エントリ一覧のページで問題が起きています。
一ページ目から<xsl:for-each select="navi">で次ページに移ろうとすると、表示が一ページ目のままになってしまいます。

http://hoge.hoge/contents/booka.php?chapterid=1http://hoge.hoge/booka1/ でアクセスできるようにしています。
次ページに移ろうとすると http://hoge.hoge/booka1/?pageno=2&chapterid=1 になります。
http://hoge.hoge/contents/booka.php?pag ... hapterid=1 を叩くと正常に二ページ目が表示されます。

http://httpd.apache.org/docs/1.3/mod/mo ... ewriteRule を見たのですが意味が分かりませんでした。

どうかお知恵を貸してください。

CMS Designer 1.1.6b
PHP 4.4.4
Apache 1.3.37
最後に編集したユーザー luis on 2007年9月12日(水) 20:54 [ 編集 1 回目 ]

luis
アクティブユーザー
記事: 20
登録日時: 2007年1月08日(月) 17:35

詳細

投稿記事 by luis » 2007年9月12日(水) 20:52

root─┬─cmsd──data──entry───┬─booka──booka.00001.xml等
    │                      └─bookb──bookb.00001.xml等
    ├─contents─┬─booka.php(エントリ一覧)
    │         ├─bookb.php(エントリ一覧)
    │         └─bookatext.php(エントリ)
    └─index.php

[site.config.xml]
<entry name="booka" schema="medium" caption="小説A"/>
<entry name="bookb" schema="medium" caption="小説B"/>

[medium.schema.xml]
<data name="chapterid" type="int" caption="章番" group="True" />
<data name="chapter" type="text" caption="章" />
<data name="section" type="text" caption="節" />
<data name="body" type="textarea" caption="本文" output="html2" />
<data name="footnote" type="textarea" caption="脚注" output="html2" />

[medium.list.default.design.xsl]
<xsl:for-each select="navi"><xsl:for-each select="next"><a href="{@href}" rel="next">次へ</a></xsl:for-each>

[booka.php]
<?php require_once( "../cmsd/include/view.php.inc" ); ?>
<cmsd:entrylist name="booka" design="default" rows="10" navigation="on"><cmsd:group key="chapterid"/></cmsd:entrylist>

[index.php]
<?php require_once( "cmsd/include/view.php.inc" ); ?>
<a href="booka1/">小説A 第一章</a>
<a href="booka2/">小説A 第二章</a>
<a href="bookb1/">小説B 第一章</a>

[.htaccess]
RewriteEngine on
RewriteRule ^([a-z]+)([0-9])/$ contents/$1\.php?chapterid=$2 [L]
RewriteRule ^([a-z]+)([0-9])/([0-9]+)\.html$ contents/$1text\.php?eid=$2 [L]
最後に編集したユーザー luis on 2007年9月18日(火) 21:42 [ 編集 2 回目 ]

webmaster
Site Admin
記事: 1451
登録日時: 2004年12月10日(金) 10:09

Re: RewriteRule が分かりません

投稿記事 by webmaster » 2007年9月13日(木) 14:42

 luisさん、ご質問ありがとうございます。
 
 mod_rewriteを使ってパラメータをディレクトリに偽装する方法は、そのパラメータに
ついての深い理解と、mod_rewrite(特に正規表現)に関する深い理解がないと難しい
ものとなっております。
 
 詳細な情報も頂いており、情報としては充分かと思うのですが、mod_rewriteに
についてはそれほど詳しいわけではないので、ご回答を差し上げるにはこちらで
実際に同様の環境を作っての試行錯誤が必要となってしまいます。

 申し訳ありませんがその時間を取る事が困難な為、考え方だけのご説明でご勘弁下さい。
 その上で、個別のご不明点があればご説明させて頂きたいと思いますが、
正規表現そのものが分からない、等の場合にはなかなか難しいかもしれません。

 /booka1/
 
 というURLを、
 
 /contents/booka.php?chapterid=1
 
 という実アドレスに置換する部分までは、非常にうまく行っていると思います。
 問題は、ご指摘の通り、
 
 /booka1/?pageno=2&chapterid=1
 
 のようなアクセスがあった場合です。
 
 現在のRewriteRuleでは、
 
 RewriteRule ^([a-z]+)([0-9])/$ contents/$1\.php?chapterid=$2 [L]
 
 という内容で置換を行っています。
 この、「^([a-z]+)([0-9])/$」という正規表現だと、
 
 /booka1/
 
 はヒットしても、
 
 /booka1/?pageno=2&chapterid=1
 
 はヒットしません。
 
 そこで、もう一つ、「/booka1/?pageno=2&chapterid=1」のようなリクエストを
ヒットさせる為のRewriteRuleを追加で書く必要があります。
 ルール内容は、既存のものに加えて pageno=X の X を認識してパラメータに
追加するというものです。それ以外のパラメータは無視するようにします。
 
 試していないので適当ですが、
 
 RewriteRule ^([a-z]+)([0-9])/\?pageno=([0-9]+)(.*)$ contents/$1\.php?pageno=$3&chapterid=$2 [L]
 
 のような感じになるかと思います。
 このまま動けばそれで良いのですが、動かなかった場合は内容をご理解頂いた上で
いろいろと試行錯誤してみて下さい。

 以上、中途半端な回答で申し訳ありませんが、よろしくお願い致します。

luis
アクティブユーザー
記事: 20
登録日時: 2007年1月08日(月) 17:35

できました

投稿記事 by luis » 2007年9月13日(木) 20:51

返信いただきありがとうございます。

? 以降を (.*) でまとめてしまったところ、正常に二ページ目が表示されるようになりました。
URL は http://hoge.hoge/booka1/?pageno=2 となっています。
それまで表示されていた &chapterid=1 がどこにいってしまったのか謎ですが、絞り込みはできています。
できれば URL をすべて / か .html で終わるようにしたいのですが、良い方法は無いものでしょうか。

[.htaccess]
RewriteRule ^([a-z]+)([0-9])/([0-9]+)\.html$ contents/$1text\.php?eid=$3&chapterid=$2 [L]
RewriteRule ^([a-z]+)([0-9])/(.*)$ contents/$1\.php$3 [L]
RewriteRule ^([a-z]+)([0-9])/$ contents/$1\.php?chapterid=$2 [L]

三行目は二行目に含まれているような気がしたので、いちどは削除したのですが、サイトトップが何故かエラーになってしまい、戻したら直りました。

ところで、『トピックの返信通知』が、ウイルスバスターで迷惑メールと判定されてしまいました。
トレンドマイクロへ誤判定報告をしておきますね。

webmaster
Site Admin
記事: 1451
登録日時: 2004年12月10日(金) 10:09

Re: できました

投稿記事 by webmaster » 2007年9月14日(金) 11:18

 luisさん、引き続きご連絡ありがとうございます。

 &chapterid=1が消えた理由が、弊社もちょっと不思議です。
 実際には「booka1」の「1」の部分がchapteridとして与えられているはずなので、
CMS Designerの出力で navi/next/@href を使った場合には、chapteridもURLに
含まれるはずなのですが…。

 現在、デザイン定義の方は、

コード: 全て選択

<xsl:for-each select="navi">
  <xsl:for-each select="next">
    <a href="{@href}">次のページへ</a>
  </xsl:f-each>
   :
 のようになっているかと思いますが、これを

コード: 全て選択

<xsl:for-each select="navi">
  <xsl:for-each select="next">
    <a href="{@id}/">次のページへ</a>
  </xsl:f-each>
   :
 とすることで、

 /booka1/2/

 のように、pagenoをさらに階層表現のアドレスにすることができます。

 但し、このままだと、さらに次のページへ進んだ時に

 /booka1/2/3/

 のように、どんどん伸びていってしまい、NGです。
 これを避けるためには、/booka1/1/ のように、1ページ目にもちゃんと
ページ番号をつけるようにして、デザイン定義では

コード: 全て選択

<xsl:for-each select="navi">
  <xsl:for-each select="next">
    <a href="../{@id}/">次のページへ</a>
  </xsl:f-each>
   :
 のようにすればOKではないかと思います。
 もちろん、これに併せてRewriteRuleも変更する必要があります。

 こんな感じになるでしょうか。

コード: 全て選択

RewriteRule ^([a-z]+)([0-9])/([0-9]+)/$ contents/$1.php?pageno=$3&chapterid=$2 [L]
 同時に、/booka1/ だけでアクセスされた場合に、自動的に /booka1/1/ に
飛ばすようにする処理も必要です。

 ページ番号を階層的に表現するのは見た目にも良いのですが、上記のように結構
いろいろと面倒もある為、ページ番号を 1.html、2.html のように表記する方法の
方が良いかもしれません。

 これは、デザイン定義を次のようにすればOKです。

コード: 全て選択

<xsl:for-each select="navi">
  <xsl:for-each select="next">
    <a href="{@id}.html">次のページへ</a>
  </xsl:f-each>
   :
 RewriteRuleは、

コード: 全て選択

RewriteRule ^([a-z]+)([0-9])/([0-9]+)\.html$ contents/$1.php?pageno=$3&chapterid=$2 [L]
 こんな感じになるでしょうか。
 例によって試していないので、エラーなどの際にはいろいろと修正してみて
下さい。m(__)m
最後に編集したユーザー webmaster on 2007年9月14日(金) 15:28 [ 編集 1 回目 ]

luis
アクティブユーザー
記事: 20
登録日時: 2007年1月08日(月) 17:35

うまくいったとおもったのですが

投稿記事 by luis » 2007年9月14日(金) 12:58

返信いただきありがとうございます。まずは、前の投稿の訂正から。

? の文字は任意の一文字をあらわすメタキャラクターであるからエスケープすべし、という記事を見つけました。
それにしたがって \? に直したところ、元の状態に戻ってしまいました。
偶然うまく動いていただけのようです。

{@id} は、個別エントリーで eid を取得できるだけだと思っていました。
一覧で pageno としても使えるのですか。

もうすこしがんばってみます。

webmaster
Site Admin
記事: 1451
登録日時: 2004年12月10日(金) 10:09

Re: うまくいったとおもったのですが

投稿記事 by webmaster » 2007年9月14日(金) 15:43

 luisさん、私も勘違いしていたので上記の投稿は修正済みですが、

[正規表現] [置き換え後のアドレス]

 とあるとき、正規表現部分は ? や . などはエスケープする必要がありますが、
置き換え後のアドレス部分はエスケープする必要はないようです。

 {@id}については、

コード: 全て選択

<xsl:for-each select="navi">
  <xsl:for-each select="next">
 の中でのみ効果があります。XMLとXSLTに慣れていると分かるかもしれないのですが、
元々CMS Designerでは次のような感じのXMLを生成してXSLT(デザイン定義)に
渡しています。

コード: 全て選択

<entrylist ...省略...  >

  <navi allcount="25" position="2" maxpage="3" maxpagerows="10">
    <prev id="1" href="?pageno=1" />
    <page id="1" href="?pageno=1" />
    <page id="2" href="?pageno=2" />
    <page id="3" href="?pageno=3" />
    <next id="3" href="?pageno=3" />
  </navi>

  <entry id="00001" ...省略...>
    <item1>項目1の値</item1>
    <item2>項目2の値</item2>
  </entry>

  <entry id="00002" ...省略...>
    <item1>項目1の値</item1>
    <item2>項目2の値</item2>
  </entry>

</entrylist>
 <xsl:template match="entrylist"> で、カレントが entrylist要素内に移ります
ので、<xsl:for-each select="navi"> でさらに navi要素に、select="next" で
さらに next要素へとカレント(現在位置)が移ります。
 その状態で{@id}を参照すると、entrylisst/navi/next/@id が取得できるという
わけです。

 通常は <xsl:for-each select="entry"> によって 各entry要素に現在位置が
移っている状態でご利用頂く事が多いので、{@id}は /entrylist/entry/@id を
参照する、ということになります。

 本来ならば、entrylist/navi/next/@id は、@idではなく@pageno とすべき
だったのですが、設計当時の考え方にぬるい部分があり、@id でここまで来てしまった
為いまさら変更するわけにもいかず、混乱を生んでいるかと思います。
 本当に申し訳ありません。

luis
アクティブユーザー
記事: 20
登録日時: 2007年1月08日(月) 17:35

できました

投稿記事 by luis » 2007年9月18日(火) 21:23

RewriteRule の文字列の後方のアドレスはエスケープ無しで良いのですね。
{@id} の件についても、詳しい説明をありがとうございます。

先にアドバイスいただいたように {@id} を使い、エントリー一覧を連番のhtmlファイルに見せかけるようにしたところ、なんとかうまくいきました。

[.htaccess]
RewriteEngine on
RewriteRule ^([a-z]+)([0-9]+)/toc([0-9]+)\.html$ contents/$1.table.php?pageno=$3&class=$2 [L]
RewriteRule ^([a-z]+)([0-9]+)/([0-9]+)\.html$ contents/$1.text.php?eid=$3&class=$2 [L]

返信