システム2号のコバです。
突然ですがSSIという技術をご存知でしょうか?
SSIとは、Server Side Includeの略で、CGIと同じく動的にコンテンツ(HTML)を生成するための技術だとかHTMLに特別なコメントを記述すると置換してくれるとかまあ色々なところで色々説明されてるが……
要は1つのページを作ろうとした時に別ページを部品として持ってこれるからHP作るのが楽になるやつである。
だがこのSSIという技術、実はもう相当に古く枯れた技術らしい。検索すれば Google「おいおい、SSLだろ?誤字ってたから検索結果にSSL含めといたぜ!!」と言われ、フレームワークには「いや、file_get_contentあるっしょ?」とか言われるのである!!
(私が一時期検索しまくったからか、もしくは「SSIだけで検索」的なアレを指定したからか、今では普通に検索してくれるようになった)
今では色々なPHPフレームワークで、もはやSSIは対応していないらしく、ねこのしっぽのホームページで利用しているCakePHPもバージョンアップしたら使えなくなってしまったのである!!
しかし、ねこのしっぽには部品をSSIで取ってきているコンテンツがけっこういっぱいある。
それら全てを、PHP化することも出来ない(いや、厳密には出来なくは無いけど)
なので今回はフレームワークそのものを改造し、SSI対応したのである!!
本日のブログはその自分向け備忘録である。
こう↑書いておけばちょっとくらい変なことが書いてあっても許してもらえるのだ。
どこかのずんだもんもそう言っていたのだ……
閑話休題
例えばもし↓↓↓こんな感じ↓↓↓に弊社の(架空の)寿司メニューのページを表示させたいとする。

この、エクセルで10秒で作ったような表を別ページとして作り、部品として使うという想定
こう↓書いておけば良いのだ。
<div class="tekito header">
ヘッダー等々
</div>
<div class="sushi menu">
<!--#include virtual="/neko/sushimenu/nigiri" -->
</div>
<div class="tekito content">
文面がある
と思ってください
</div>
<!--#include virtual="/neko/sushimenu/nigiri" -->
↑の部分に↓のサイトで作られた表が部品として配置されて画像のようになるのである。
https://www.shippo.co.jp/neko/sushimenu/nigiri
これがCakephpでは挿入されない。
そこでerrorログを見ると
5023-15-51 11:45:14 Error: [MissingControllerException] Controller class NekoController could not be found.
Exception Attributes: array (
'class' => 'NekoController',
'plugin' => NULL,
)
リクエストが正確に解釈されていないっぽい。
と、いうことでCakephpでリクエストを処理しているCakeRequestを見てみると
if (!empty($_SERVER['PATH_INFO'])) {
return $_SERVER['PATH_INFO'];
} elseif (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], '://') === false) {
$uri = $_SERVER['REQUEST_URI'];
} elseif (isset($_SERVER['REQUEST_URI'])) {
$qPosition = strpos($_SERVER['REQUEST_URI'], '?');
if ($qPosition !== false && strpos($_SERVER['REQUEST_URI'], '://') > $qPosition) {
$uri = $_SERVER['REQUEST_URI'];
} else {
$uri = substr($_SERVER['REQUEST_URI'], strlen(Configure::read('App.fullBaseUrl')));
}
} elseif (isset($_SERVER['PHP_SELF']) && isset($_SERVER['SCRIPT_NAME'])) {
$uri = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['PHP_SELF']);
} elseif (isset($_SERVER['HTTP_X_REWRITE_URL'])) {
$uri = $_SERVER['HTTP_X_REWRITE_URL'];
} elseif ($var = env('argv')) {
$uri = $var[0];
}
なるほど、見ていない。
そこで上記をこうする
//REDIRECT_SCRIPT_NAME.shtmlを含む場合SSIと判断
if(isset($_SERVER['REDIRECT_SCRIPT_NAME']) && strpos($_SERVER['REDIRECT_SCRIPT_NAME'], '.shtml') !== false){
$uri = $_SERVER['REDIRECT_URL'];
} elseif (!empty($_SERVER['PATH_INFO'])) {
return $_SERVER['PATH_INFO'];
} elseif (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], '://') === false) {
$uri = $_SERVER['REQUEST_URI'];
} elseif (isset($_SERVER['REQUEST_URI'])) {
$qPosition = strpos($_SERVER['REQUEST_URI'], '?');
if ($qPosition !== false && strpos($_SERVER['REQUEST_URI'], '://') > $qPosition) {
$uri = $_SERVER['REQUEST_URI'];
} else {
$uri = substr($_SERVER['REQUEST_URI'], strlen(Configure::read('App.fullBaseUrl')));
}
} elseif (isset($_SERVER['PHP_SELF']) && isset($_SERVER['SCRIPT_NAME'])) {
$uri = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['PHP_SELF']);
} elseif (isset($_SERVER['HTTP_X_REWRITE_URL'])) {
$uri = $_SERVER['HTTP_X_REWRITE_URL'];
} elseif ($var = env('argv')) {
$uri = $var[0];
}
これで対象のファイルがSSIを使っているかをフレームワーク側が検知してくれるようになりました。