とりあえず、タイトル通り・・・
PHPでssiを使用し、PHPを読み込むと8kバイト以上出力する場合に該当のssiの記述の内容が取得できないというのがあるります。
これは8kバイト以内であれば問題なく動くので、ajaxなどでデータの取得や出力をすると問題ないです。
しかし、どうしてもテンプレートの状態で8kバイトを超える場合があるので、その場合はもう、力業でやるのみです。その時のを覚書としてメモしておきます。
テンプレートファイル(出力するファイル)
./tmpl/index.html
<!DOCTYPE html> <html> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta charset="UTF-8"> <meta name="description" content=""> <meta name="author" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <title></title> <!--[if lt IE 9]><script src="//cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script> <![endif]--><link rel="shortcut icon" href="icon.ico"> <style> </style> </head> <body> <!--#include virtual="/ssi/header.php" --> <dvi class="contents"> コンテンツだよ </dvi> <!--#include virtual="/ssi/footer.php" --> <script type="text/javascript"> </script> </body> </html>
phpプログラム
index.php
<?php
// セッションスタート
session_start();
// とりあえすセッションを使う
$_SESSION['count'] = 0;
// テンプレートファイル
$tpl_index = "./tmpl/index.html";
// テンプレートファイルの読込
$buf = file_get_contents($tpl_index);
// 読み込んだ内容からinclude部分のphpを抽出して、対象の内容を取得
$buf = setSsiInclude($buf);
// 出力
echo $buf;
function setSsiInclude($buf)
{
// 正規表現で該当の部分を抽出
preg_match_all("/<!--#include\s+virtual=\"(.+\.php)\"\s+-->/", $buf, $reg);
// 該当の部分がる場合のみ以下の処理
if(isset($reg[1]) && is_array($reg[1]) && count($reg[1])) {
// セッションがスタートされている場合、一旦セッションを書き込んで閉じる
if (session_status() == 2) {
session_write_close();
}
// 対象のinclude部分を読み込んで、置き換える
$tmp = "";
foreach ($reg[1] as $n=>$v) {
$s = strpos($buf, $reg[0][$n]);
$tmp.= substr($buf, 0, $s);
// includeのアドレスを読み込む
$tmp.= getData($v);
$buf = substr($buf, ($s+strlen($reg[0][$n])));
}
$tmp.= $buf;
$buf = $tmp;
// セッションが使える状態で、セッションがスタートされていない場合、
//セッションをスタートする
if (session_status() == 1) {
session_start();
}
}
// 置換後の内容を返す
return $buf;
}
/**
* アドレスの内容を取得
*/
function getData($url)
{
// アクセスしてきたときのプロトコルを取得
$protcol = isset($_SERVER['HTTPS'])?'https://':'http://';
// アクセスしてきたときのホスト名
$host = $_SERVER['HTTP_HOST'];
// URIの作る
$uri = $protcol . $host . $url;
// apacheを使っているので、リクエストのヘッダーを取得
$arh = apache_request_headers();
// ユーザーエージェントは、アクセス元のブラウザのを使用、無い場合はてきとうなものを使用
$ua = isset($_SERVER['HTTP_USER_AGENT'])?$_SERVER['HTTP_USER_AGENT']:'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0';
// コンテキスト設定
$opts = array(
'http' => array(
'method' => "GET",
'header' => array(
"User-Agent: {$ua}",
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language: ja,en-US;q=0.7,en;q=0.3",
"Accept-Encoding: gzip, deflate, br",
),
'timeout' => 3.0,
'ignore_errors' => true,
),
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true,
),
);
// cookieがある場合、そのままcookieを設定※phpのセッションcookieで使用しているのでこうする
if (is_array($arh)){
$opts['http']['header'][] = "Cookie: ". $arh['Cookie'];
}
$ctx = stream_context_create($opts);
// 内容を取得します。で、いちおうゴミを取り除く
return trim(file_get_contents($uri, false, $ctx));
}
header.php
<?php session_start(); $_SESSION['count'] = isset($_SESSION['count'])?($_SESSION['count']+1):1; $count = $_SESSION['count']; ?><div>HEADER <?php echo $count; ?></div>
footer.php
<?php session_start(); $_SESSION['count'] = isset($_SESSION['count'])?($_SESSION['count']+1):1; $count = $_SESSION['count']; ?><div>FOOTER <?php echo $count; ?></div>
出力される内容
<!DOCTYPE html> <html> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta charset="UTF-8"> <meta name="description" content=""> <meta name="author" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <title></title> <!--[if lt IE 9]><script src="//cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script> <![endif]--><link rel="shortcut icon" href="icon.ico"> <style> </style> </head> <body> <div>HEADER 1</div> <dvi class="contents"> コンテンツだよ </dvi> <div>FOOTER 2</div> <script type="text/javascript"> </script> </body> </html>