【PHP】シャープ(#)をパラメータとして受け取る方法【Ajax】

この記事は最終更新から4年以上が経過しています。情報が古くなっている可能性があります。

こんにちは、しばです。
この前、シャープをパラメータとして受け取ってphpで使いたいなぁという機会がありました。
例であげるとこういうURLです。
https://exampla.com/?target=man_#01
https://exampla.com/?target=woman_#02

これまでパラメータに#をつけることを考えたことがなかったんですが、調べてみるとphpではシャープ(#)はURLとして受け取れないんですね (°Д°;
javascript(jQuery)では取得・処理ができるんですが、できれば通常のパラメータと同じくそのままphpで受け取って処理を行いたい…

ということで色々検証してみました。
結論としてajaxを使うことで実現できたので、そのやり方とサンプルデータをまとめてみました。

どうしてもシャープ入りパラメータをphpで使いたい時の参考になれば幸いです!

何故phpではシャープを受け取れないのか

なぜ消えるかといえばブラウザがサーバへリクエストする時点で#以下は切り捨ててしまうからです。
#以下はfragment identifierという特殊な意味を持つ記号なので普通のURLには使えません。

引用元)https://teratail.com/questions/48179

このような理由とのこと。常識だったんだろうか…知りませんでした(´Д`;)

実際に確認してみます。

例)ローカル環境でhttp://localhost/test.php?target=man_#01でアクセス 「man_#01」を取得したい
echo $_GET[“target”]; :「man_
echo $_SERVER[“REQUEST_URI”]; :「/test.php?target=man_

確かにどちらもシャープ以下が切れてしまう…_:(´ཀ`」 ∠):

javascriptで処理する方法ならシャープも含めて取得できるので、jsで処理できればいいや!という方は”JavaScript URL パラメーター”等で検索するとちょうどいいサンプルが出てくるかと思います。

ただ今回はjsで一部の値を書き換えるというより、がっつり表示内容を変更したり処理を行ったりしたいところ。

phpでシャープをパラメータとして使うには

ということで、Ajaxを利用して、jsを噛ませるだけでphpではほぼ普通の処理で動かせるように作ってみました。

メインphpファイル

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>

<?php

if(isset($_POST['sexType'])){ //Ajaxで送信された値を受け取る
	$param = $_POST['sexType'];
	echo $param;

	if($param == 'man_#01'){
		?><h1>man_#01用ページ!</h1><?php
	}else if($param == 'man_#02'){
		?><h1>man_#02用ページ!</h1><?php
	}else{
		?><h1>一般向けページ!</h1><?php
	}
}
?>

<script
  src="https://code.jquery.com/jquery-3.4.1.js"
  integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
  crossorigin="anonymous"></script>
<script src="test.js"></script>

</body>
</html>

jsファイル

const URL_PARAM_NAME_TARGET = 'target';

$(function() {
  let sexType = getUrlParam(URL_PARAM_NAME_TARGET);
  
  function getUrlParam(name, url) {
    if (!url) url = window.location.href;
    name = name.replace(/[\[\]]/g, "\\$&");
    var regex = new RegExp("[?&]" + name + "(=([^&]*)|&|$)"),
        results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, " "));
  }

  $.ajax({
    type: "POST",
    url: "test.php",
    data: {"sexType": sexType},
        success: function(data){
            $('html').html(data);
        }
    });
});

DEMO

上記ファイルに各パラメータでアクセスした結果が次の通りです。

  • test.php?target=man_#01
    →パラメータ「man_#01」と「man_#01用ページ!」が出力
  • test.php?target=man_#02
    →パラメータ「man_#02」と「man_#02用ページ!」が出力
  • test.php?target=●●●●●
    →man_#01、man_#02以外の場合、アクセスしたパラメータ「●●●●●」と「一般向けページ!」が出力

処理の流れはこんな感じ。

  1. (jquery) パラメータを取得
  2. (jquery) 取得した値をajaxでtest.phpへPOST送信
  3. (test.php) $_POST[]で送信されてきた値を取得。書かれているphpを処理
  4. (jquery) 3.で処理に成功した場合、HTML要素配下を、php処理済みのtest.phpのhtmlコードで書き換え

少量コンテンツじゃないと時間がかかりそうだとか色々と問題が出そうな方法ではありますが、極シンプルなコンテンツで行う分には、本当に普通のphpページとしてパラメータ取得できていて特に問題なさそう。

本来のphpと違うところは、php処理部分がソースコードに表示されないことです。
javascriptと同じように開発者ツールでは確認できるんですが、右クリックで[ソースコードを表示]しても、この方法でphp出力されたマークアップは出てきません。

それに関連してか、Google botにもこの方法でphp出力された内容は認識されないようです。
モバイルフレンドリーテストにかけたところ、レンダリング画面でphp出力部分が出力されていないことを確認。
Google botはjsは処理・認識してもこのケースは厳しそうですね。

実装自体は可能だがデメリットも多い

無事実装はできましたが、

  • コンテンツのボリュームが大きかったりjsが入ってたりすると、処理に時間がかかったり干渉する可能性がある
  • おそらくGoogle botに認識されない

こういったところが実用性、SEO面ともにネックかなぁと思います。

今回の想定ケースはなかなかないと思いますが、クライアントの都合やシステムの連携とか色々止むを得ない都合もあるかも知れません。
どうしてもやりたい時の参考になれば幸いです!