質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.13%

.htaccessファイルで後方参照のドルマークがそのまま表示される

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 634

chef

score 15

お世話になります。

現在、htaccessファイルへ処理命令を自動で記述するプログラムを開発しています。

悩んでいるのは、.htaccessファイルに処理命令を書き込む際のエスケープ漏れ?についてです。

エスケープ漏れというか、単に私の書き方が悪いのだと思うので、ぜひお知恵を借りたいです。

処理内容

まず、最初の処理で以下のような文字列が生成されます。

スラッグの部分を正規表現で取得して新しいサイトでそれを使おうとしています。

<IfModule mod_rewrite.c>
#元のURL:http:old.com
RewriteEngine On
RewriteCond %{HTTP_HOST} ^old\.com
RewriteCond %{REQUEST_URI} ^\/hello\-world\/?$
RewriteRule ^([^\/]+?)?$ https\:\/\/new\.com\/\$1 [R=302,L]
</IfModule>

その後、この文字列と元々htaccessファイルにあった文字列を合体させて、file_put_content関数で既存のhtaccessファイルと置き換えます。

file_put_contents( htaccessのパス, 新しく生成されたhtaccessファイル );

問題点

基本的に問題なく動くのですが、極稀に後方参照のために記述している$1がそのまま表示されます。

本来は、リダイレクトのURLは「https://new.com/hello-world」になるはずが、「https://new.com/$1」となります。

この現象が起こる環境が特定できず、困っております。

文字コードが原因なのかなと、mb_convert_encoding関数でutf-8に変換してみたのですが、そういう問題ではなさそうです。

このコードは何がいけないのでしょうか?

追記

非常にざっくりとですが、今現在このようなリダイレクト処理を自動化するプログラムを作っています。

【ファイルA】
#URLはユーザーに入力してもらう
$new_site_url = 'https://new.com/';
#http://old.com/hello-worldの記事にアクセスした時にリダイレクトする
$rewrite_cond  = 'RewriteCond %{HTTP_HOST} ^old\.com$'.PHP_EOL;
$rewrite_cond .= 'RewriteCond %{REQUEST_URI} ^/hello-world/?$'.PHP_EOL;
$rewrite_rule  = 'RewriteRule ^([^/]+?)?$ '.$new_site_url.'$1 [R=302,L]';

#ファイルB用に処理内容を出力
$text = <<< EOM
<IfModule mod_rewrite.c>
RewriteEngine On
$rewrite_cond
$rewrite_rule
</IfModule>
EOM

echo $text;
【ファイルB】

ob_start();
require_once(ファイルA);
$new_text = ob_get_clean(); //ファイルAから処理内容を受け取って変数へ

$htaccess = ABSPATH.'.htaccess';

$htaccess_text = @file_get_contents( $htaccess );

$htaccess_text = $new_text.PHP_EOL.$htaccess_text;

file_put_contents($htaccess, $htaccess_text);

なぜ$1だけピンポイントで消えるのか、どこで消えているのかが、理解できませんでした。

詳細なコードはGithubの方で公開しているので、もしコードに不備があるようでしたらご覧いただけると嬉しいです。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+3

直接の原因は、$1と書くべきところを\$1と書いているので、$1の機能が無効になっているからです。
他にも、間違った、あるいは、無意味な\が多いです。記号には全部\を付けると思っていませんか?

RewriteEngine On
RewriteCond %{HTTP_HOST} ^old\.com$
RewriteCond %{REQUEST_URI} ^/hello-world/?$
RewriteRule ^([^/]+?)?$ https://new.com/$1 [R=302,L]


さらに簡単に、

RewriteEngine On
RewriteCond %{HTTP_HOST} ^old\.com$
RewriteRule ^(hello-world)/?$ https://new.com/$1 [R=302,L]

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/09 10:20

    大変貴重なご意見ありがとうございます。とても心強いです。
    間違ったエスケープ、無意味なエスケープ、まさに仰るかと思います。
    無知を承知でお聞きしたいのですが、$1をバックスラッシュなしで記述した場合、file_put_contents後のファイルからその部分だけピンポイントで消えてしまうことがあるのですが、これはどういう現象が起きているのでしょうか?
    参考になればと記事の方に関連コードを追記させていただくので、ご意見お聞かせ願えれば幸いです。

    キャンセル

  • 2019/03/09 11:54

    ファイルAのコードだと、EOMの後ろに ; がないので、文法エラーですね。

    > file_put_contents後のファイルからその部分だけピンポイントで消えてしまうことがあるのですが、これはどういう現象が起きているのでしょうか?

    現象が発生するコードを載せてください。

    キャンセル

  • 2019/03/09 11:55

    あと、<IfModule mod_rewrite.c> と </IfModule> の行も有害無益なので消しましょう。

    キャンセル

  • 2019/03/09 15:54

    文法エラーの件タイプミスでした、ご指摘ありがとうございます。
    <IfModule mod_rewrite.c> と </IfModule>の部分も確かにいらないですね。削除します。
    $1が消えてしまう現象、よくよく調べてみたら正規表現云々ではなく、文字列を受け取って処理をするPHP側に問題がある可能性が高くなりました。
    雑に処理をしているか、凡ミスをしていると思うので、そっちの方を確認してみます。
    色々と勉強になりました。ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.13%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる