とりあえず、タイトル通り・・・
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>