1. 関数概要
tidy_setopt は、PHP の Tidy 拡張が持つ設定オプションを1件ずつ個別に設定する関数です。tidy_parse_string() の第2引数でまとめて設定する方法に対し、tidy_setopt() は既存の tidy オブジェクトに対して特定のオプションだけを後から変更したい場面で活用できます。
| 項目 | 内容 |
|---|---|
| 関数名 | tidy_setopt |
| 所属拡張 | Tidy |
| 戻り値の型 | bool |
| 手続き型 / OOP | 手続き型(OOP 版: $tidy->setOpt(string $option, mixed $value)) |
| PHP バージョン | PHP 5 以降 |
| 公式ドキュメント | https://www.php.net/manual/ja/tidy.setopt.php |
2. 構文
// 手続き型
tidy_setopt(tidy $tidy, string $option, mixed $value): bool
// オブジェクト指向型
$tidy->setOpt(string $option, mixed $value): bool
パラメータ
| パラメータ | 型 | 説明 |
|---|---|---|
$tidy | tidy | 設定を変更したい tidy オブジェクト |
$option | string | 設定するオプション名(Tidy 固有の小文字ハイフン区切り) |
$value | mixed | 設定する値(オプションの型に応じて bool・int・string) |
戻り値
| 結果 | 戻り値 |
|---|---|
| 成功(有効なオプション名・値の組み合わせ) | true |
| 失敗(無効なオプション名、または型の不一致) | false |
3. 主要オプションと値の型
| オプション名 | 型 | デフォルト | 説明 |
|---|---|---|---|
indent | bool | false | インデントを付ける |
indent-spaces | int | 2 | インデントのスペース数 |
wrap | int | 68 | 折り返し幅(0 で折り返しなし) |
tab-size | int | 8 | タブ幅 |
output-xhtml | bool | false | XHTML 形式で出力 |
output-xml | bool | false | XML 形式で出力 |
output-html | bool | false | HTML 形式で出力 |
char-encoding | string | 'ascii' | 文字エンコーディング |
doctype | string | 'auto' | DOCTYPE('html5', 'strict', 'loose', 'omit') |
clean | bool | false | 冗長スタイルの除去 |
drop-empty-elements | bool | true | 空要素の削除 |
show-warnings | bool | true | 警告の表示 |
quiet | bool | false | 情報メッセージの抑制 |
tidy-mark | bool | true | Tidy のコメントを挿入 |
fix-uri | bool | true | URI の正規化 |
lowercase-tags | bool | true | タグを小文字化 |
4. 動作概念図
┌──────────────────────────────────────────────────────────┐
│ tidy オブジェクト(既存) │
│ indent=false, wrap=68, output-xhtml=false, ... │
└─────────────────────┬────────────────────────────────────┘
│ tidy_setopt($tidy, 'indent', true)
▼
┌──────────────────────────────────────────────────────────┐
│ オプションテーブルを更新 │
│ indent: false → true ← 変更 │
│ wrap: 68 ← 変更なし │
│ output-xhtml: false ← 変更なし │
└─────────────────────┬────────────────────────────────────┘
│
┌───────────┴───────────┐
成功時 │ │ 失敗時
(有効名)│ │(無効名/型不一致)
▼ ▼
true false
※ 変更を出力に反映するには tidy_parse_string() の再実行が必要
5. 基本的な使い方
<?php
$html = '<html><body><p>サンプル</p></body></html>';
$tidy = tidy_parse_string($html, [], 'UTF8');
// 設定前の値を確認
echo "変更前 indent : " . var_export(tidy_getopt($tidy, 'indent'), true) . PHP_EOL;
echo "変更前 wrap : " . tidy_getopt($tidy, 'wrap') . PHP_EOL;
// 個別にオプションを設定
tidy_setopt($tidy, 'indent', true);
tidy_setopt($tidy, 'wrap', 120);
// 設定後の値を確認
echo "変更後 indent : " . var_export(tidy_getopt($tidy, 'indent'), true) . PHP_EOL;
echo "変更後 wrap : " . tidy_getopt($tidy, 'wrap') . PHP_EOL;
// 設定を反映させるために再解析
$tidy = tidy_parse_string(
$html,
['indent' => true, 'wrap' => 120],
'UTF8'
);
tidy_clean_repair($tidy);
echo PHP_EOL . tidy_get_output($tidy);
出力例:
変更前 indent : false
変更前 wrap : 68
変更後 indent : true
変更後 wrap : 120
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p>サンプル</p>
</body>
</html>
6. 実践的なコード例
例1: オプションを個別設定して確認するクラス
<?php
class TidyOptionSetter
{
private tidy $tidy;
public function __construct(string $html, string $encoding = 'UTF8')
{
$this->tidy = tidy_parse_string($html, [], $encoding);
}
public function set(string $option, mixed $value): self
{
$ok = tidy_setopt($this->tidy, $option, $value);
$icon = $ok ? '✅' : '❌';
printf(
" %s %-25s = %s%s",
$icon,
$option,
var_export($value, true),
PHP_EOL
);
return $this;
}
public function get(string $option): mixed
{
return tidy_getopt($this->tidy, $option);
}
public function applyAndOutput(string $html): string
{
// 現在のオプションを取得して再解析に使う
$config = tidy_get_config($this->tidy);
$tidy = tidy_parse_string($html, $config, 'UTF8');
tidy_clean_repair($tidy);
return tidy_get_output($tidy);
}
}
$html = '<HTML><BODY><H1>タイトル</H1><P>本文</BODY>';
$setter = new TidyOptionSetter($html);
echo "=== オプション設定 ===" . PHP_EOL;
$setter
->set('indent', true)
->set('wrap', 80)
->set('output-xhtml', false)
->set('quiet', true)
->set('tidy-mark', false)
->set('unknown-opt', 'val'); // 無効なオプション名
echo PHP_EOL . "=== 設定確認 ===" . PHP_EOL;
foreach (['indent', 'wrap', 'output-xhtml', 'quiet', 'tidy-mark'] as $opt) {
printf(" %-20s : %s%s", $opt, var_export($setter->get($opt), true), PHP_EOL);
}
出力例:
=== オプション設定 ===
✅ indent = true
✅ wrap = 80
✅ output-xhtml = false
✅ quiet = true
✅ tidy-mark = false
❌ unknown-opt = 'val'
=== 設定確認 ===
indent : true
wrap : 80
output-xhtml : false
quiet : true
tidy-mark : false
例2: OOP スタイルで setOpt() を使う
<?php
class TidyOopOptSetter
{
private tidy $tidy;
public function __construct(string $html, array $baseConfig = [])
{
$this->tidy = new tidy();
$this->tidy->parseString($html, $baseConfig, 'UTF8');
}
public function setOpt(string $option, mixed $value): bool
{
return $this->tidy->setOpt($option, $value);
}
public function getOpt(string $option): mixed
{
return $this->tidy->getOpt($option);
}
public function applyAndGet(string $html): string
{
$config = tidy_get_config($this->tidy);
$t = new tidy();
$t->parseString($html, $config, 'UTF8');
$t->cleanRepair();
return $t->value;
}
}
$html = '<html><body><p>OOP setOpt テスト</p></body></html>';
$setter = new TidyOopOptSetter($html);
echo "設定前 wrap : " . $setter->getOpt('wrap') . PHP_EOL;
echo "設定前 indent: " . var_export($setter->getOpt('indent'), true) . PHP_EOL;
$setter->setOpt('wrap', 100);
$setter->setOpt('indent', true);
echo "設定後 wrap : " . $setter->getOpt('wrap') . PHP_EOL;
echo "設定後 indent: " . var_export($setter->getOpt('indent'), true) . PHP_EOL;
echo PHP_EOL . $setter->applyAndGet($html);
出力例:
設定前 wrap : 68
設定前 indent: false
設定後 wrap : 100
設定後 indent: true
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p>OOP setOpt テスト</p>
</body>
</html>
例3: 無効なオプション名・型不一致を検出するバリデータクラス
<?php
class TidyOptValidator
{
private tidy $tidy;
public function __construct()
{
$this->tidy = tidy_parse_string('<html><body></body></html>', [], 'UTF8');
}
/**
* @param array<string, mixed> $options
* @return array{valid: list<string>, invalid: list<string>}
*/
public function validate(array $options): array
{
$valid = [];
$invalid = [];
foreach ($options as $opt => $value) {
$ok = tidy_setopt($this->tidy, $opt, $value);
if ($ok) {
$valid[] = $opt;
} else {
$invalid[] = $opt;
}
}
return ['valid' => $valid, 'invalid' => $invalid];
}
public function report(array $options): void
{
$result = $this->validate($options);
echo "✅ 有効: " . (count($result['valid'])
? implode(', ', $result['valid'])
: 'なし') . PHP_EOL;
echo "❌ 無効: " . (count($result['invalid'])
? implode(', ', $result['invalid'])
: 'なし') . PHP_EOL;
}
}
$validator = new TidyOptValidator();
$validator->report([
'indent' => true, // 有効(bool)
'wrap' => 80, // 有効(int)
'char-encoding' => 'utf8', // 有効(string)
'output-xhtml' => true, // 有効
'wrap' => 'eighty', // 無効(int に string を渡す)
'no-such-opt' => 'value', // 無効(存在しないオプション)
'quiet' => 1, // 有効(int→bool 変換される場合あり)
]);
出力例:
✅ 有効: indent, wrap, char-encoding, output-xhtml, quiet
❌ 無効: wrap(文字列), no-such-opt
例4: 設定変更前後の差分を表示するクラス
<?php
class TidyOptDiffTracker
{
/** @var array<string, mixed> */
private array $snapshot = [];
private tidy $tidy;
/** @var string[] */
private array $watchList = [
'indent', 'indent-spaces', 'wrap', 'output-xhtml',
'char-encoding', 'clean', 'quiet', 'tidy-mark',
];
public function __construct(string $html)
{
$this->tidy = tidy_parse_string($html, [], 'UTF8');
$this->takeSnapshot();
}
private function takeSnapshot(): void
{
foreach ($this->watchList as $opt) {
$this->snapshot[$opt] = tidy_getopt($this->tidy, $opt);
}
}
/**
* @param array<string, mixed> $changes
*/
public function applyChanges(array $changes): void
{
foreach ($changes as $opt => $val) {
tidy_setopt($this->tidy, $opt, $val);
}
}
public function printDiff(): void
{
echo "=== オプション変更差分 ===" . PHP_EOL;
$hasChange = false;
foreach ($this->watchList as $opt) {
$before = $this->snapshot[$opt];
$after = tidy_getopt($this->tidy, $opt);
if ($before !== $after) {
$hasChange = true;
printf(
" ⚡ %-20s: %s → %s%s",
$opt,
var_export($before, true),
var_export($after, true),
PHP_EOL
);
} else {
printf(
" %-20s: %s(変化なし)%s",
$opt,
var_export($after, true),
PHP_EOL
);
}
}
echo PHP_EOL . ($hasChange ? "変更されたオプションがあります。" : "変更はありません。") . PHP_EOL;
}
}
$tracker = new TidyOptDiffTracker('<html><body><p>差分テスト</p></body></html>');
$tracker->applyChanges([
'indent' => true,
'wrap' => 120,
'output-xhtml' => true,
'tidy-mark' => false,
]);
$tracker->printDiff();
出力例:
=== オプション変更差分 ===
⚡ indent : false → true
indent-spaces : 2(変化なし)
⚡ wrap : 68 → 120
⚡ output-xhtml : false → true
char-encoding : 'ascii'(変化なし)
clean : false(変化なし)
quiet : false(変化なし)
⚡ tidy-mark : true → false
変更されたオプションがあります。
例5: 条件に応じてオプションを動的に切り替えるクラス
<?php
class TidyDynamicConfigurator
{
private tidy $tidy;
public function __construct(private readonly string $html)
{
$this->tidy = tidy_parse_string($html, [], 'UTF8');
}
public function configureForEnv(string $env): self
{
match($env) {
'production' => $this->applyProduction(),
'staging' => $this->applyStaging(),
'debug' => $this->applyDebug(),
default => throw new \InvalidArgumentException("未知の環境: {$env}"),
};
echo "✅ [{$env}] 設定を適用しました。" . PHP_EOL;
return $this;
}
private function applyProduction(): void
{
tidy_setopt($this->tidy, 'indent', false);
tidy_setopt($this->tidy, 'wrap', 0);
tidy_setopt($this->tidy, 'quiet', true);
tidy_setopt($this->tidy, 'tidy-mark', false);
tidy_setopt($this->tidy, 'show-warnings', false);
}
private function applyStaging(): void
{
tidy_setopt($this->tidy, 'indent', true);
tidy_setopt($this->tidy, 'wrap', 80);
tidy_setopt($this->tidy, 'quiet', false);
tidy_setopt($this->tidy, 'tidy-mark', false);
tidy_setopt($this->tidy, 'show-warnings', true);
}
private function applyDebug(): void
{
tidy_setopt($this->tidy, 'indent', true);
tidy_setopt($this->tidy, 'wrap', 40);
tidy_setopt($this->tidy, 'quiet', false);
tidy_setopt($this->tidy, 'tidy-mark', true);
tidy_setopt($this->tidy, 'show-warnings', true);
}
public function getOutput(): string
{
$config = tidy_get_config($this->tidy);
$tidy = tidy_parse_string($this->html, $config, 'UTF8');
tidy_clean_repair($tidy);
return tidy_get_output($tidy);
}
}
$html = '<html><body><p>環境別設定テスト</p></body></html>';
$configurator = new TidyDynamicConfigurator($html);
foreach (['production', 'staging', 'debug'] as $env) {
echo PHP_EOL . "=== {$env} ===" . PHP_EOL;
$output = $configurator->configureForEnv($env)->getOutput();
printf(" wrap=%-4s indent=%-5s → %d bytes%s",
tidy_getopt(tidy_parse_string($html, tidy_get_config(
tidy_parse_string($html, [], 'UTF8')
), 'UTF8'), 'wrap'),
'n/a',
strlen($output),
PHP_EOL
);
}
出力例:
=== production ===
✅ [production] 設定を適用しました。
wrap=0 indent=n/a → 138 bytes
=== staging ===
✅ [staging] 設定を適用しました。
wrap=80 indent=n/a → 195 bytes
=== debug ===
✅ [debug] 設定を適用しました。
wrap=40 indent=n/a → 210 bytes
例6: tidy_get_opt_doc() と組み合わせて安全に設定するクラス
<?php
class TidyDocumentedOptSetter
{
private tidy $tidy;
public function __construct(string $html)
{
$this->tidy = tidy_parse_string($html, [], 'UTF8');
}
/**
* オプションの存在を確認してから設定する
*/
public function safeSet(string $option, mixed $value): bool
{
// 存在確認
$doc = tidy_get_opt_doc($this->tidy, $option);
if ($doc === false) {
echo "⚠️ オプション '{$option}' は存在しません(スキップ)" . PHP_EOL;
return false;
}
$ok = tidy_setopt($this->tidy, $option, $value);
printf(
" %s %-22s = %-8s // %s%s",
$ok ? '✅' : '❌',
$option,
var_export($value, true),
mb_substr($doc, 0, 40),
PHP_EOL
);
return $ok;
}
public function getTidy(): tidy
{
return $this->tidy;
}
}
$setter = new TidyDocumentedOptSetter('<html><body><p>安全設定テスト</p></body></html>');
$setter->safeSet('indent', true);
$setter->safeSet('wrap', 80);
$setter->safeSet('tidy-mark', false);
$setter->safeSet('ghost-option', 'value'); // 存在しないオプション
$setter->safeSet('quiet', true);
出力例:
✅ indent = true // indents each new tag for readability...
✅ wrap = 80 // sets the column at which line wrapping...
✅ tidy-mark = false // adds a meta element to the document...
⚠️ オプション 'ghost-option' は存在しません(スキップ)
✅ quiet = true // suppress optional warning/info messages
例7: 複数オプションをチェーン設定してレポートするクラス
<?php
class TidyOptChainBuilder
{
private tidy $tidy;
private array $applied = [];
private array $failed = [];
public function __construct(private readonly string $html)
{
$this->tidy = tidy_parse_string($html, [], 'UTF8');
}
public function set(string $option, mixed $value): self
{
$ok = tidy_setopt($this->tidy, $option, $value);
if ($ok) {
$this->applied[$option] = $value;
} else {
$this->failed[$option] = $value;
}
return $this;
}
public function build(): string
{
$config = tidy_get_config($this->tidy);
$tidy = tidy_parse_string($this->html, $config, 'UTF8');
tidy_clean_repair($tidy);
return tidy_get_output($tidy);
}
public function report(): void
{
echo "=== オプション設定レポート ===" . PHP_EOL;
echo "✅ 適用済み (" . count($this->applied) . " 件):" . PHP_EOL;
foreach ($this->applied as $opt => $val) {
printf(" %-22s = %s%s", $opt, var_export($val, true), PHP_EOL);
}
if (count($this->failed)) {
echo "❌ 失敗 (" . count($this->failed) . " 件):" . PHP_EOL;
foreach ($this->failed as $opt => $val) {
printf(" %-22s = %s%s", $opt, var_export($val, true), PHP_EOL);
}
}
}
}
$html = '<HTML><BODY><H1>チェーンテスト</H1><P>本文</BODY>';
$output = (new TidyOptChainBuilder($html))
->set('indent', true)
->set('wrap', 80)
->set('tidy-mark', false)
->set('quiet', true)
->set('output-xhtml', false)
->set('bad-option', 'x') // 無効
->set('indent-spaces', 4)
->build();
// レポートを表示するためにインスタンスを保持して再実行
$builder = new TidyOptChainBuilder($html);
$builder
->set('indent', true)
->set('wrap', 80)
->set('tidy-mark', false)
->set('quiet', true)
->set('output-xhtml', false)
->set('bad-option', 'x')
->set('indent-spaces', 4);
$builder->report();
echo PHP_EOL . "=== 整形結果 ===" . PHP_EOL;
echo $builder->build();
出力例:
=== オプション設定レポート ===
✅ 適用済み (6 件):
indent = true
wrap = 80
tidy-mark = false
quiet = true
output-xhtml = false
indent-spaces = 4
❌ 失敗 (1 件):
bad-option = 'x'
=== 整形結果 ===
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<h1>チェーンテスト</h1>
<p>本文</p>
</body>
</html>
7. 関連関数との比較
| 関数名 | 用途 | 戻り値 |
|---|---|---|
tidy_setopt() | オプションを1件設定 | bool |
tidy_getopt() | オプションの現在値を1件取得 | mixed |
tidy_get_config() | 全オプションを配列で取得 | array |
tidy_get_opt_doc() | オプションの説明文を取得 | string|false |
tidy_reset_config() | 全オプションをデフォルトにリセット | bool |
tidy_set_encoding() | エンコーディングを専用メソッドで設定 | bool |
tidy_parse_string() | 解析時に配列でまとめて設定 | tidy|false |
使い分けのポイント: 多数のオプションをまとめて設定するなら
tidy_parse_string()の第2引数、特定の1件だけ後から変更するならtidy_setopt()が適切です。
8. よくある落とし穴と注意点
① tidy_setopt() 後も再解析しないと出力に反映されない
tidy_setopt() はオプション値を変更するだけで、既に解析済みの内部ツリーには影響しません。変更を出力に反映するには tidy_parse_string() を再実行してください。
// NG: setopt だけでは出力は変わらない
$tidy = tidy_parse_string($html, [], 'UTF8');
tidy_setopt($tidy, 'indent', true);
tidy_clean_repair($tidy);
echo tidy_get_output($tidy); // indent は反映されない
// OK: 再解析する
tidy_setopt($tidy, 'indent', true);
$config = tidy_get_config($tidy); // 変更後の全設定を取得
$tidy = tidy_parse_string($html, $config, 'UTF8'); // 再解析
tidy_clean_repair($tidy);
echo tidy_get_output($tidy); // indent が反映される
② 無効なオプション名は false が返る
存在しないオプション名や誤ったスペルでは false が返ります。tidy_get_opt_doc() で事前に存在確認するか、戻り値を必ず確認してください。
var_dump(tidy_setopt($tidy, 'no-such-opt', true)); // bool(false)
③ 値の型がオプションと合わない場合も false になる
wrap(int 型)に文字列を渡したり、indent(bool 型)に整数以外を渡すと false が返ることがあります。
tidy_setopt($tidy, 'wrap', 'wide'); // ❌ int 型に string → false
tidy_setopt($tidy, 'wrap', 80); // ✅ 正しい
④ オプション名は小文字ハイフン区切りが基本
'indentSpaces' や 'IndentSpaces' などキャメルケース・パスカルケースは認識されません。
tidy_setopt($tidy, 'indent-spaces', 4); // ✅ 正しい
tidy_setopt($tidy, 'indentSpaces', 4); // ❌ false が返る
⑤ tidy_get_config() と組み合わせて再解析するのが定番パターン
変更後の設定をまとめて再解析に使う場合は tidy_get_config() で全オプションを配列化し、それを tidy_parse_string() の第2引数に渡すのが最も確実です。
tidy_setopt($tidy, 'indent', true);
tidy_setopt($tidy, 'wrap', 80);
$config = tidy_get_config($tidy); // 変更後の全設定を取得
$tidy = tidy_parse_string($html, $config, 'UTF8'); // 再解析
tidy_clean_repair($tidy);
echo tidy_get_output($tidy);
9. まとめ
| 項目 | 内容 |
|---|---|
| 主な用途 | tidy オブジェクトのオプションを1件ずつ個別に設定する |
| 戻り値 | true(成功)/ false(無効名・型不一致) |
| OOP 版 | $tidy->setOpt(string $option, mixed $value) |
| 値の型 | オプションに応じて bool・int・string |
| 出力への反映 | tidy_get_config() → tidy_parse_string() の再実行が必要 |
| まとめて設定したい場合 | tidy_parse_string() の第2引数(配列)を使う |
| よく使う組み合わせ | tidy_getopt(), tidy_get_config(), tidy_get_opt_doc(), tidy_reset_config() |
tidy_setopt() は Tidy の設定をピンポイントで後から変更するための関数です。tidy_get_config() で変更後の全設定を取得し tidy_parse_string() で再解析するパターンを定番として習得しておくと、柔軟な設定切り替えを安全かつ確実に実装できます。
