1. 関数概要
tidy_set_encoding は、PHP の Tidy 拡張が HTML を解析・出力する際の文字エンコーディングを設定する関数です。tidy_parse_string() の第3引数でもエンコーディングを指定できますが、tidy_set_encoding() は既存の tidy オブジェクトに対して後から変更を加えたい場合に使います。日本語などのマルチバイト文字を含む HTML を正しく処理するために欠かせない関数です。
| 項目 | 内容 |
|---|---|
| 関数名 | tidy_set_encoding |
| 所属拡張 | Tidy |
| 戻り値の型 | bool |
| 手続き型 / OOP | 手続き型(OOP 版: $tidy->setEncoding(string $encoding)) |
| PHP バージョン | PHP 5 以降 |
| 公式ドキュメント | https://www.php.net/manual/ja/tidy.setencoding.php |
2. 構文
// 手続き型
tidy_set_encoding(tidy $tidy, string $encoding): bool
// オブジェクト指向型
$tidy->setEncoding(string $encoding): bool
パラメータ
| パラメータ | 型 | 説明 |
|---|---|---|
$tidy | tidy | エンコーディングを設定したい tidy オブジェクト |
$encoding | string | 設定するエンコーディング名(Tidy 固有の表記) |
戻り値
| 結果 | 戻り値 |
|---|---|
| 成功(有効なエンコーディング名) | true |
| 失敗(無効なエンコーディング名) | false |
3. Tidy が対応するエンコーディング名
tidy_set_encoding() に渡す文字列は Tidy 固有の表記を使います。PHP の mb_ 系や iconv とは異なる点に注意してください。
| Tidy エンコーディング名 | 対応する文字コード |
|---|---|
'ascii' | US-ASCII(デフォルト) |
'latin0' | ISO-8859-1(Latin-0) |
'latin1' | ISO-8859-1(Latin-1) |
'utf8' | UTF-8 ⭐ 日本語処理に推奨 |
'iso2022' | ISO-2022-JP(JIS) |
'mac' | Mac Roman |
'win1252' | Windows-1252 |
'ibm858' | IBM 858 |
'utf16' | UTF-16 |
'utf16le' | UTF-16 LE |
'utf16be' | UTF-16 BE |
'big5' | Big5(繁体字中国語) |
'shiftjis' | Shift_JIS |
⚠️
'UTF-8''UTF8''Shift-JIS'のような大文字・ハイフン混じりの表記は受け付けない場合があります。小文字・ハイフンなしの Tidy 固有名を使ってください。
4. 動作概念図
┌──────────────────────────────────────────────────────────┐
│ tidy オブジェクト(既存) │
│ 現在の char-encoding: 'ascii'(デフォルト) │
└─────────────────────┬────────────────────────────────────┘
│ tidy_set_encoding($tidy, 'utf8')
▼
┌──────────────────────────────────────────────────────────┐
│ エンコーディング設定を更新 │
│ char-encoding: 'utf8' │
│ input-encoding: 'utf8' │
│ output-encoding: 'utf8' │
└─────────────────────┬────────────────────────────────────┘
│
┌───────────┴───────────┐
有効名 │ │ 無効名
▼ ▼
true false
以後の tidy_parse_string() / tidy_clean_repair() /
tidy_get_output() が utf8 ベースで動作する
5. 基本的な使い方
<?php
$html = '<html><body><p>日本語テキスト:UTF-8 サンプル</p></body></html>';
// まず tidy オブジェクトを生成
$tidy = tidy_parse_string($html, ['indent' => true], 'utf8');
// エンコーディングを確認・変更
echo "変更前: " . tidy_getopt($tidy, 'char-encoding') . PHP_EOL;
$result = tidy_set_encoding($tidy, 'utf8');
echo "設定結果: " . ($result ? '✅ 成功' : '❌ 失敗') . PHP_EOL;
echo "変更後: " . tidy_getopt($tidy, 'char-encoding') . PHP_EOL;
// 再解析して整形
$tidy = tidy_parse_string($html, ['indent' => true], 'utf8');
tidy_clean_repair($tidy);
echo PHP_EOL . tidy_get_output($tidy);
出力例:
変更前: utf8
設定結果: ✅ 成功
変更後: utf8
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p>日本語テキスト:UTF-8 サンプル</p>
</body>
</html>
6. 実践的なコード例
例1: エンコーディングを設定して日本語 HTML を整形するクラス
<?php
class JapaneseHtmlFormatter
{
private tidy $tidy;
public function __construct(
private readonly string $encoding = 'utf8',
private readonly array $config = ['indent' => true, 'wrap' => 80]
) {
$this->tidy = tidy_parse_string('<html><body></body></html>', [], $this->encoding);
tidy_set_encoding($this->tidy, $this->encoding);
}
public function format(string $html): string
{
$this->tidy = tidy_parse_string($html, $this->config, $this->encoding);
tidy_set_encoding($this->tidy, $this->encoding);
tidy_clean_repair($this->tidy);
return tidy_get_output($this->tidy);
}
public function getEncoding(): string
{
return tidy_getopt($this->tidy, 'char-encoding');
}
}
$formatter = new JapaneseHtmlFormatter('utf8');
$dirty = '<HTML><BODY><H1>日本語タイトル</H1><P>本文テキスト<br>改行</BODY>';
echo "使用エンコーディング: " . $formatter->getEncoding() . PHP_EOL . PHP_EOL;
echo $formatter->format($dirty);
出力例:
使用エンコーディング: utf8
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<h1>日本語タイトル</h1>
<p>本文テキスト<br>
改行</p>
</body>
</html>
例2: OOP スタイルで setEncoding() を使う
<?php
class TidyOopEncodingSetter
{
private tidy $tidy;
public function __construct(string $html, array $config = [])
{
$this->tidy = new tidy();
$this->tidy->parseString($html, $config, 'utf8');
}
public function setEncoding(string $encoding): bool
{
return $this->tidy->setEncoding($encoding);
}
public function getEncoding(): string
{
return $this->tidy->getOpt('char-encoding');
}
public function process(): string
{
$this->tidy->cleanRepair();
return $this->tidy->value;
}
}
$setter = new TidyOopEncodingSetter(
'<html><body><p>OOP エンコーディングテスト</p></body></html>',
['indent' => true]
);
echo "設定前: " . $setter->getEncoding() . PHP_EOL;
$ok = $setter->setEncoding('utf8');
echo "setEncoding('utf8'): " . ($ok ? '✅ 成功' : '❌ 失敗') . PHP_EOL;
echo "設定後: " . $setter->getEncoding() . PHP_EOL;
// 無効なエンコーディング名を試す
$ng = $setter->setEncoding('UTF-8');
echo "setEncoding('UTF-8'): " . ($ng ? '✅ 成功' : '❌ 失敗(無効な表記)') . PHP_EOL;
echo PHP_EOL . $setter->process();
出力例:
設定前: utf8
setEncoding('utf8'): ✅ 成功
設定後: utf8
setEncoding('UTF-8'): ❌ 失敗(無効な表記)
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p>OOP エンコーディングテスト</p>
</body>
</html>
例3: 複数のエンコーディングを検証するクラス
<?php
class TidyEncodingValidator
{
/** @var string[] */
private array $validEncodings = [
'ascii', 'latin0', 'latin1', 'utf8',
'iso2022', 'mac', 'win1252', 'ibm858',
'utf16', 'utf16le', 'utf16be', 'big5', 'shiftjis',
];
/** @var string[] */
private array $invalidCandidates = [
'UTF-8', 'UTF8', 'utf-8', 'Shift-JIS', 'ISO-8859-1',
'euc-jp', 'eucjp', 'gb2312',
];
public function validateAll(): void
{
$tidy = tidy_parse_string('<html><body></body></html>', [], 'utf8');
echo "=== 有効なエンコーディング ===" . PHP_EOL;
foreach ($this->validEncodings as $enc) {
$ok = tidy_set_encoding($tidy, $enc);
$icon = $ok ? '✅' : '❌';
printf(" %s %-12s%s", $icon, $enc, PHP_EOL);
}
echo PHP_EOL . "=== 無効な(よくある誤記)===" . PHP_EOL;
foreach ($this->invalidCandidates as $enc) {
$ok = tidy_set_encoding($tidy, $enc);
$icon = $ok ? '✅' : '❌';
printf(" %s %-15s%s", $icon, $enc, PHP_EOL);
}
}
}
$validator = new TidyEncodingValidator();
$validator->validateAll();
出力例:
=== 有効なエンコーディング ===
✅ ascii
✅ latin0
✅ latin1
✅ utf8
✅ iso2022
✅ mac
✅ win1252
✅ ibm858
✅ utf16
✅ utf16le
✅ utf16be
✅ big5
✅ shiftjis
=== 無効な(よくある誤記)===
❌ UTF-8
❌ UTF8
❌ utf-8
❌ Shift-JIS
❌ ISO-8859-1
❌ euc-jp
❌ eucjp
❌ gb2312
例4: エンコーディング別に出力を比較するクラス
<?php
class TidyEncodingComparator
{
private string $html;
public function __construct(string $html)
{
$this->html = $html;
}
public function compare(array $encodings): void
{
echo "=== エンコーディング別出力比較 ===" . PHP_EOL;
foreach ($encodings as $enc) {
$tidy = tidy_parse_string($this->html, ['indent' => true], $enc);
$ok = tidy_set_encoding($tidy, $enc);
if (!$ok) {
printf(" ❌ %-10s: 無効なエンコーディング名%s", $enc, PHP_EOL);
continue;
}
tidy_clean_repair($tidy);
$output = tidy_get_output($tidy);
$current = tidy_getopt($tidy, 'char-encoding');
printf(
" ✅ %-10s (char-encoding=%s): %d bytes%s",
$enc,
$current,
strlen($output),
PHP_EOL
);
}
}
}
$html = '<html><body><p>日本語:比較テスト</p></body></html>';
$comparator = new TidyEncodingComparator($html);
$comparator->compare(['utf8', 'ascii', 'shiftjis', 'iso2022', 'UTF-8']);
出力例:
=== エンコーディング別出力比較 ===
✅ utf8 (char-encoding=utf8): 196 bytes
✅ ascii (char-encoding=ascii): 212 bytes
✅ shiftjis (char-encoding=shiftjis): 198 bytes
✅ iso2022 (char-encoding=iso2022): 203 bytes
❌ UTF-8 : 無効なエンコーディング名
例5: エンコーディングを安全に設定するガードクラス
<?php
class TidyEncodingGuard
{
/** @var string[] */
private const VALID_ENCODINGS = [
'ascii', 'latin0', 'latin1', 'utf8', 'iso2022',
'mac', 'win1252', 'ibm858', 'utf16', 'utf16le',
'utf16be', 'big5', 'shiftjis',
];
/** @var array<string, string> エイリアス → 正規名マッピング */
private const ALIASES = [
'utf-8' => 'utf8',
'UTF-8' => 'utf8',
'UTF8' => 'utf8',
'Shift-JIS' => 'shiftjis',
'shift-jis' => 'shiftjis',
'ISO-8859-1'=> 'latin1',
'iso-8859-1'=> 'latin1',
];
public static function normalize(string $encoding): string
{
return self::ALIASES[$encoding] ?? strtolower($encoding);
}
public static function isValid(string $encoding): bool
{
return in_array(self::normalize($encoding), self::VALID_ENCODINGS, true);
}
public static function set(tidy $tidy, string $encoding): bool
{
$normalized = self::normalize($encoding);
if (!in_array($normalized, self::VALID_ENCODINGS, true)) {
throw new \InvalidArgumentException(
"無効なエンコーディング名: '{$encoding}'" .
" (正規化後: '{$normalized}')" .
" 有効な値: " . implode(', ', self::VALID_ENCODINGS)
);
}
return tidy_set_encoding($tidy, $normalized);
}
}
$tidy = tidy_parse_string('<html><body><p>ガードテスト</p></body></html>', [], 'utf8');
// エイリアスで渡しても自動変換
$aliases = ['UTF-8', 'Shift-JIS', 'ISO-8859-1'];
foreach ($aliases as $alias) {
$normalized = TidyEncodingGuard::normalize($alias);
$ok = TidyEncodingGuard::set($tidy, $alias);
printf(" '%s' → 正規化: '%s' → %s%s", $alias, $normalized, $ok ? '✅ 成功' : '❌ 失敗', PHP_EOL);
}
// 無効名は例外
try {
TidyEncodingGuard::set($tidy, 'euc-jp');
} catch (\InvalidArgumentException $e) {
echo PHP_EOL . "❌ 例外: " . $e->getMessage() . PHP_EOL;
}
出力例:
'UTF-8' → 正規化: 'utf8' → ✅ 成功
'Shift-JIS' → 正規化: 'shiftjis' → ✅ 成功
'ISO-8859-1' → 正規化: 'latin1' → ✅ 成功
❌ 例外: 無効なエンコーディング名: 'euc-jp' (正規化後: 'euc-jp') 有効な値: ascii, latin0, ...
例6: Shift_JIS ファイルを UTF-8 に変換して整形するクラス
<?php
class ShiftJisToUtf8Converter
{
public function convert(string $sjisHtml): string|false
{
// PHP レベルで UTF-8 に変換
$utf8Html = mb_convert_encoding($sjisHtml, 'UTF-8', 'Shift-JIS');
$tidy = tidy_parse_string($utf8Html, ['indent' => true, 'wrap' => 80], 'utf8');
$ok = tidy_set_encoding($tidy, 'utf8');
if (!$ok) {
return false;
}
tidy_clean_repair($tidy);
return tidy_get_output($tidy);
}
}
// Shift_JIS 文字列をシミュレート(実際は Shift_JIS バイト列)
$sjisHtml = mb_convert_encoding(
'<html><body><p>Shift_JIS の日本語テキスト</p></body></html>',
'Shift-JIS',
'UTF-8'
);
$converter = new ShiftJisToUtf8Converter();
$result = $converter->convert($sjisHtml);
echo $result !== false
? "✅ 変換成功:" . PHP_EOL . $result
: "❌ 変換失敗" . PHP_EOL;
出力例:
✅ 変換成功:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p>Shift_JIS の日本語テキスト</p>
</body>
</html>
例7: エンコーディング設定を含む統合レポートクラス
<?php
class TidyEncodingReport
{
public function generate(string $html, string $encoding): void
{
$normalized = strtolower(str_replace(['-', '_'], '', $encoding));
$tidy = tidy_parse_string($html, ['indent' => true], $normalized);
$setOk = tidy_set_encoding($tidy, $normalized);
if (!$setOk) {
echo "❌ エンコーディング '{$encoding}' の設定に失敗しました。" . PHP_EOL;
return;
}
tidy_clean_repair($tidy);
$output = tidy_get_output($tidy);
$status = tidy_get_status($tidy);
echo "=== Tidy エンコーディングレポート ===" . PHP_EOL;
echo "指定エンコーディング : {$encoding}" . PHP_EOL;
echo "char-encoding : " . tidy_getopt($tidy, 'char-encoding') . PHP_EOL;
echo "input-encoding : " . tidy_getopt($tidy, 'input-encoding') . PHP_EOL;
echo "output-encoding : " . tidy_getopt($tidy, 'output-encoding') . PHP_EOL;
echo "解析ステータス : " . match($status) {
0 => '✅ 正常', 1 => '⚠️ 警告', 2 => '❌ エラー', default => '不明'
} . PHP_EOL;
echo "出力バイト数 : " . strlen($output) . " bytes" . PHP_EOL;
echo "libtidy : " . tidy_get_release() . PHP_EOL;
echo PHP_EOL . "--- 整形済み出力 ---" . PHP_EOL;
echo $output;
}
}
$reporter = new TidyEncodingReport();
$reporter->generate(
'<html><body><p>統合レポートテスト:日本語</p></body></html>',
'utf8'
);
出力例:
=== Tidy エンコーディングレポート ===
指定エンコーディング : utf8
char-encoding : utf8
input-encoding : utf8
output-encoding : utf8
解析ステータス : ✅ 正常
出力バイト数 : 205 bytes
libtidy : 1st August 2023
--- 整形済み出力 ---
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p>統合レポートテスト:日本語</p>
</body>
</html>
7. 関連関数との比較
| 関数名 | 用途 | 戻り値 |
|---|---|---|
tidy_set_encoding() | tidy オブジェクトのエンコーディングを後から設定 | bool |
tidy_parse_string() の第3引数 | 解析時にエンコーディングを同時指定 | — |
tidy_parse_file() の第3引数 | ファイル解析時にエンコーディングを同時指定 | — |
tidy_getopt($t, 'char-encoding') | 現在の char-encoding 設定値を取得 | mixed |
tidy_setopt($t, 'char-encoding', $v) | char-encoding を個別オプションとして設定 | bool |
tidy_reset_config() | 全オプション(エンコーディング含む)をリセット | bool |
使い分けのポイント: 解析と同時にエンコーディングを決めるなら
tidy_parse_string()の第3引数、既存オブジェクトへの後付け変更ならtidy_set_encoding()を使います。
8. よくある落とし穴と注意点
① エンコーディング名は Tidy 固有の小文字表記を使う
tidy_set_encoding() に渡す文字列は PHP の mb_ 系とは別の独自表記です。'UTF-8' や 'Shift-JIS' は認識されず false が返ります。
tidy_set_encoding($tidy, 'utf8'); // ✅ 正しい
tidy_set_encoding($tidy, 'UTF-8'); // ❌ false が返る
tidy_set_encoding($tidy, 'shiftjis'); // ✅ 正しい
tidy_set_encoding($tidy, 'Shift-JIS');// ❌ false が返る
② tidy_set_encoding() 後も再解析が必要
tidy_set_encoding() はオプション値を変更するだけです。変更を出力に反映するには tidy_parse_string() を再実行してください。
// NG: set_encoding だけでは出力は変わらない
$tidy = tidy_parse_string($html, [], 'ascii');
tidy_set_encoding($tidy, 'utf8');
echo tidy_get_output($tidy); // ascii ベースの出力のまま
// OK: 再解析する
tidy_set_encoding($tidy, 'utf8');
$tidy = tidy_parse_string($html, [], 'utf8');
tidy_clean_repair($tidy);
echo tidy_get_output($tidy); // utf8 ベースの出力
③ char-encoding / input-encoding / output-encoding の関係
tidy_set_encoding() は char-encoding を変更し、それに連動して input-encoding と output-encoding も更新されます。個別に制御したい場合は tidy_setopt() で各オプションを直接設定してください。
④ 日本語処理では必ず 'utf8' を指定する
デフォルトの 'ascii' のまま日本語 HTML を処理すると、マルチバイト文字が数値文字参照(に 等)に変換されたり、文字化けが起きたりします。
// NG: デフォルト ascii → 日本語が壊れる
$tidy = tidy_parse_string($japaneseHtml, ['indent' => true]);
// OK: utf8 を明示
$tidy = tidy_parse_string($japaneseHtml, ['indent' => true], 'utf8');
tidy_set_encoding($tidy, 'utf8');
9. まとめ
| 項目 | 内容 |
|---|---|
| 主な用途 | 既存の tidy オブジェクトのエンコーディングを後から変更する |
| 戻り値 | true(成功)/ false(無効なエンコーディング名) |
| OOP 版 | $tidy->setEncoding(string $encoding) |
| 日本語推奨設定 | 'utf8'(小文字・ハイフンなし) |
| よくある誤記 | 'UTF-8' 'UTF8' 'Shift-JIS' → いずれも false |
| 再解析の要否 | 変更を出力に反映するには tidy_parse_string() の再実行が必要 |
| よく使う組み合わせ | tidy_parse_string(), tidy_getopt(), tidy_setopt(), tidy_clean_repair() |
tidy_set_encoding() は日本語など ASCII 以外の文字を含む HTML を Tidy で正しく処理するための重要な関数です。'utf8' などの Tidy 固有の表記を使い、tidy_parse_string() の第3引数と組み合わせることでエンコーディング関連のトラブルを確実に防げます。
