[覚書]PHPプログラムでSSIにPHPを設定[php]

とりあえず、タイトル通り・・・

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>
スポンサーリンク

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください