1. 関数概要
tidy_get_output は、PHP の Tidy 拡張によって解析・修復・整形された HTML/XHTML ドキュメントを文字列として取得する関数です。tidy_clean_repair() でクリーニングを行った後にこの関数を呼び出すことで、修正済みの HTML を変数に格納し、出力・保存・加工に利用できます。
| 項目 | 内容 |
|---|---|
| 関数名 | tidy_get_output |
| 所属拡張 | Tidy |
| 戻り値の型 | string |
| 手続き型 / OOP | 手続き型(OOP 版: (string) $tidy キャストまたは $tidy->value プロパティ) |
| PHP バージョン | PHP 5 以降 |
| 公式ドキュメント | https://www.php.net/manual/ja/tidy.getoutput.php |
2. 構文
// 手続き型
tidy_get_output(tidy $tidy): string
// オブジェクト指向型(プロパティアクセス)
$html = $tidy->value;
// オブジェクト指向型(文字列キャスト)
$html = (string) $tidy;
パラメータ
| パラメータ | 型 | 説明 |
|---|---|---|
$tidy | tidy | tidy_parse_string() 等で生成し、tidy_clean_repair() を適用済みの tidy オブジェクト |
戻り値
クリーニング・整形済みの HTML/XHTML 文字列。
注意:
tidy_clean_repair()を呼び出す前にtidy_get_output()を実行すると、修復前の元のソースが返されます。必ずクリーニング後に呼び出してください。
3. 動作概念図
┌──────────────────────────────────────────────────────────────┐
│ 入力: 不正・未整形の HTML 文字列 │
│ "<html><body><p>未閉じタグ<br>改行なし</body>" │
└───────────────────────┬──────────────────────────────────────┘
│ tidy_parse_string()
▼
┌──────────────────────────────────────────────────────────────┐
│ Tidy 解析エンジン(tidy オブジェクト生成) │
│ ・DOCTYPE 検出 │
│ ・構文エラー収集 │
│ ・内部ツリー構築 │
└───────────────────────┬──────────────────────────────────────┘
│ tidy_clean_repair()
▼
┌──────────────────────────────────────────────────────────────┐
│ 修復・整形処理 │
│ ・タグの自動補完 ・インデント整形 │
│ ・属性の正規化 ・文字エンコード変換 │
│ ・DOCTYPE 付与 ・XHTML 変換(オプション) │
└───────────────────────┬──────────────────────────────────────┘
│ tidy_get_output()
▼
┌──────────────────────────────────────────────────────────────┐
│ 出力: 整形済み HTML/XHTML 文字列(string) │
│ "<!DOCTYPE html>\n<html>\n <head>...</head>\n <body>..." │
└──────────────────────────────────────────────────────────────┘
4. 基本的な使い方
<?php
// 意図的に不正な HTML を用意
$html = '<html><body><p>閉じタグなし<br>テキスト</body>';
$tidy = tidy_parse_string($html, ['indent' => true, 'wrap' => 80], 'UTF8');
tidy_clean_repair($tidy);
$output = tidy_get_output($tidy);
echo $output;
出力例:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p>閉じタグなし<br>
テキスト</p>
</body>
</html>
5. 実践的なコード例
例1: HTML を整形して文字列で受け取る基本クラス
<?php
class HtmlFormatter
{
private tidy $tidy;
public function __construct(
private readonly array $config = ['indent' => true, 'wrap' => 80]
) {}
public function format(string $html): string
{
$this->tidy = tidy_parse_string($html, $this->config, 'UTF8');
tidy_clean_repair($this->tidy);
return tidy_get_output($this->tidy);
}
}
$formatter = new HtmlFormatter();
$dirty = '<html><body><P>段落<br>テキスト<div>ブロック</div></P></body></html>';
echo $formatter->format($dirty);
出力例:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p>段落<br>
テキスト</p>
<div>ブロック</div>
</body>
</html>
例2: OOP スタイルで $tidy->value を使う
<?php
class TidyOopOutputFetcher
{
private tidy $tidy;
public function __construct(string $html, array $config = [])
{
$this->tidy = new tidy();
$this->tidy->parseString($html, $config, 'UTF8');
$this->tidy->cleanRepair();
}
public function getOutput(): string
{
// OOP でのプロパティアクセス
return $this->tidy->value;
}
public function getCasted(): string
{
// 文字列キャストでも同じ結果
return (string) $this->tidy;
}
}
$html = '<html><body><p>OOPサンプル</p></body></html>';
$fetcher = new TidyOopOutputFetcher($html, ['indent' => true]);
echo "--- value プロパティ ---" . PHP_EOL;
echo $fetcher->getOutput();
echo PHP_EOL . "--- string キャスト ---" . PHP_EOL;
echo $fetcher->getCasted();
出力例:
--- value プロパティ ---
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p>OOPサンプル</p>
</body>
</html>
--- string キャスト ---
(同一の出力)
例3: 整形済み HTML をファイルに保存するクラス
<?php
class HtmlFileSaver
{
public function __construct(
private readonly string $outputDir
) {
if (!is_dir($this->outputDir)) {
mkdir($this->outputDir, 0755, true);
}
}
public function save(string $html, string $filename): string
{
$config = ['indent' => true, 'wrap' => 120, 'doctype' => 'html5'];
$tidy = tidy_parse_string($html, $config, 'UTF8');
tidy_clean_repair($tidy);
$output = tidy_get_output($tidy);
$filepath = $this->outputDir . DIRECTORY_SEPARATOR . $filename;
file_put_contents($filepath, $output);
echo "保存完了: {$filepath} (" . strlen($output) . " bytes)" . PHP_EOL;
return $filepath;
}
}
$saver = new HtmlFileSaver('/tmp/tidy_output');
$dirty = '<HTML><BODY><h1>タイトル<p>本文テキスト</BODY>';
$saver->save($dirty, 'cleaned.html');
出力例:
保存完了: /tmp/tidy_output/cleaned.html (152 bytes)
例4: 修復前後を比較して差分を表示するクラス
<?php
class HtmlDiffViewer
{
public function compare(string $original): void
{
$tidy = tidy_parse_string($original, ['indent' => true], 'UTF8');
tidy_clean_repair($tidy);
$repaired = tidy_get_output($tidy);
$originalLines = explode("\n", $original);
$repairedLines = explode("\n", $repaired);
echo "=== 修復前: " . count($originalLines) . " 行 / "
. strlen($original) . " bytes ===" . PHP_EOL;
echo $original . PHP_EOL . PHP_EOL;
echo "=== 修復後: " . count($repairedLines) . " 行 / "
. strlen($repaired) . " bytes ===" . PHP_EOL;
echo $repaired . PHP_EOL;
}
}
$viewer = new HtmlDiffViewer();
$viewer->compare('<html><body><p>未閉じ<b>太字</body>');
出力例:
=== 修復前: 1 行 / 38 bytes ===
<html><body><p>未閉じ<b>太字</body>
=== 修復後: 14 行 / 210 bytes ===
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p>未閉じ<b>太字</b></p>
</body>
</html>
例5: XHTML 形式で出力するクラス
<?php
class XhtmlConverter
{
private array $config = [
'output-xhtml' => true,
'indent' => true,
'wrap' => 80,
'char-encoding' => 'utf8',
];
public function convert(string $html): string
{
$tidy = tidy_parse_string($html, $this->config, 'UTF8');
tidy_clean_repair($tidy);
return tidy_get_output($tidy);
}
public function isXhtml(string $output): bool
{
return str_contains($output, 'xmlns="http://www.w3.org/1999/xhtml"');
}
}
$converter = new XhtmlConverter();
$html = '<html><body><br><img src="test.jpg"></body></html>';
$xhtml = $converter->convert($html);
echo $xhtml . PHP_EOL;
echo "XHTML 変換確認: " . ($converter->isXhtml($xhtml) ? '✅ OK' : '❌ NG') . PHP_EOL;
出力例:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<br />
<img src="test.jpg" alt="" />
</body>
</html>
XHTML 変換確認: ✅ OK
例6: エラー情報と整形済み出力をセットで返すクラス
<?php
class TidyAnalysisResult
{
public function __construct(
public readonly string $output,
public readonly int $status,
public readonly string $errorBuffer,
public readonly int $htmlVersion,
) {}
}
class TidyFullAnalyzer
{
public function analyze(string $html, array $config = []): TidyAnalysisResult
{
$tidy = tidy_parse_string($html, $config + ['indent' => true], 'UTF8');
tidy_clean_repair($tidy);
return new TidyAnalysisResult(
output: tidy_get_output($tidy),
status: tidy_get_status($tidy),
errorBuffer: tidy_get_error_buffer($tidy) ?? '',
htmlVersion: tidy_get_html_ver($tidy),
);
}
}
$analyzer = new TidyFullAnalyzer();
$result = $analyzer->analyze('<html><body><p>テスト<br></body></html>');
echo "=== 整形済み出力 ===" . PHP_EOL;
echo $result->output . PHP_EOL;
echo "=== 解析結果 ===" . PHP_EOL;
echo "ステータス : " . $result->status . PHP_EOL;
echo "HTMLバージョン: " . $result->htmlVersion . PHP_EOL;
echo "エラーバッファ: " . ($result->errorBuffer ?: 'なし') . PHP_EOL;
出力例:
=== 整形済み出力 ===
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p>テスト<br></p>
</body>
</html>
=== 解析結果 ===
ステータス : 0
HTMLバージョン: 0
エラーバッファ: なし
例7: 複数ページを一括整形して配列で返すクラス
<?php
class BulkHtmlCleaner
{
private array $config;
public function __construct(array $config = ['indent' => true, 'wrap' => 80])
{
$this->config = $config;
}
/**
* @param array<string, string> $pages キー: ページ名, 値: HTML文字列
* @return array<string, string> キー: ページ名, 値: 整形済みHTML
*/
public function cleanAll(array $pages): array
{
$results = [];
foreach ($pages as $name => $html) {
$tidy = tidy_parse_string($html, $this->config, 'UTF8');
tidy_clean_repair($tidy);
$results[$name] = tidy_get_output($tidy);
}
return $results;
}
public function printSummary(array $results): void
{
echo "=== 一括整形サマリー ===" . PHP_EOL;
foreach ($results as $name => $output) {
printf("%-15s => %d bytes%s", $name, strlen($output), PHP_EOL);
}
}
}
$cleaner = new BulkHtmlCleaner();
$pages = [
'index' => '<html><body><h1>トップ</h1><p>概要</body>',
'about' => '<html><body><h2>会社概要<p>内容</h2></body></html>',
'contact' => '<HTML><BODY><FORM><INPUT type=text></FORM></BODY></HTML>',
];
$results = $cleaner->cleanAll($pages);
$cleaner->printSummary($results);
echo PHP_EOL . "=== index ページの整形結果 ===" . PHP_EOL;
echo $results['index'];
出力例:
=== 一括整形サマリー ===
index => 183 bytes
about => 187 bytes
contact => 219 bytes
=== index ページの整形結果 ===
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<h1>トップ</h1>
<p>概要</p>
</body>
</html>
6. 関連関数との比較
| 関数名 | 用途 | 戻り値 |
|---|---|---|
tidy_get_output() | 整形済み HTML を文字列で取得 | string |
tidy_clean_repair() | HTML の修復・整形を実行(出力は行わない) | bool |
tidy_parse_string() | HTML 文字列を解析して tidy オブジェクト生成 | tidy|false |
tidy_parse_file() | HTML ファイルを解析して tidy オブジェクト生成 | tidy|false |
tidy_get_error_buffer() | 解析・修復時のエラーメッセージを取得 | string|false |
tidy_get_status() | 解析結果のステータス(0=正常, 1=警告, 2=エラー)を取得 | int |
tidy_get_html_ver() | 解析済み HTML のバージョン番号を取得 | int |
7. よくある落とし穴と注意点
① tidy_clean_repair() を呼ぶ前に実行すると未修復のソースが返る
最も重要な注意点です。tidy_get_output() は内部バッファをそのまま返すため、tidy_clean_repair() を忘れると修復前の HTML が返ります。
// NG: cleanRepair なしで出力
$tidy = tidy_parse_string($html, [], 'UTF8');
echo tidy_get_output($tidy); // 修復されていない可能性がある
// OK: cleanRepair 後に出力
$tidy = tidy_parse_string($html, [], 'UTF8');
tidy_clean_repair($tidy);
echo tidy_get_output($tidy); // 修復済み
② OOP では $tidy->value または (string) $tidy で同等の結果が得られる
手続き型の tidy_get_output($tidy) と、OOP の $tidy->value および (string) $tidy はすべて同じ出力を返します。プロジェクトのスタイルに合わせて統一してください。
// 以下の3つはすべて同じ結果
$out1 = tidy_get_output($tidy);
$out2 = $tidy->value;
$out3 = (string) $tidy;
③ 設定オプションによって出力内容が大きく変わる
indent・wrap・output-xhtml・doctype などの設定によって出力形式が異なります。意図しない DOCTYPE や XML 宣言が付与されることがあるため、tidy_get_config() で現在の設定を確認しながら調整してください。
④ 文字エンコードの指定を忘れない
tidy_parse_string() の第3引数でエンコードを明示的に指定しないと、日本語が文字化けする場合があります。
// NG: エンコード未指定(文字化けの恐れ)
$tidy = tidy_parse_string($html, []);
// OK: UTF-8 を明示指定
$tidy = tidy_parse_string($html, [], 'UTF8');
8. まとめ
| 項目 | 内容 |
|---|---|
| 主な用途 | Tidy で修復・整形した HTML を文字列として取得する |
| 戻り値 | string(整形済み HTML/XHTML) |
| 必須の前提 | tidy_clean_repair() を先に呼び出すこと |
| OOP 版 | $tidy->value または (string) $tidy |
| よく使う組み合わせ | tidy_parse_string() → tidy_clean_repair() → tidy_get_output() |
| 注意点 | エンコード指定・clean_repair 忘れ・設定による出力変化 |
tidy_get_output() は Tidy を使った HTML 処理の最終ステップとして必ず登場する関数です。tidy_parse_string() → tidy_clean_repair() → tidy_get_output() の3ステップをひとつのパターンとして覚えておくと、HTML の自動修復・整形をスムーズに実装できます。
