【PHP8.x】DOMDocument::resolveExternalsプロパティの使い方
resolveExternalsプロパティの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
resolveExternalsプロパティは、PHPのDOMDocumentクラスにおいて、XML文書が外部エンティティを参照する際に、その外部エンティティを解決(ロード)するかどうかを制御するための真偽値(trueまたはfalse)を保持するプロパティです。
このプロパティをtrueに設定すると、DOMDocumentオブジェクトがXML文書を解析する際、文書内に記述された外部のDTD(Document Type Definition)ファイルや、別のXMLファイルなどの外部リソースへの参照を解決し、その内容をDOMツリーに含めようとします。一方で、falseに設定すると、これらの外部参照は無視され、パーサーは外部リソースをロードしようとしません。
PHP 8以降では、このresolveExternalsプロパティのデフォルト値はfalseに変更されました。これはセキュリティ上の理由から非常に重要な変更点です。外部エンティティの解決を許可すると、XML外部エンティティ攻撃(XXE攻撃)と呼ばれるセキュリティ上の脆弱性が生じる可能性があります。悪意のあるXML文書を処理した場合、システム内の機密情報が漏洩したり、不要なファイルが読み込まれたりする危険性があるため、信頼できないソースからのXML文書を扱う際には、このプロパティをfalseに設定し続けるか、明示的にfalseに設定することが強く推奨されます。
特定のビジネスロジックで外部DTDやXMLスキーマを参照し、文書の完全な構造検証や変換に外部ファイルのロードが不可欠な場合にのみ、セキュリティリスクを十分に理解した上で、このプロパティをtrueに設定することを検討してください。
構文(syntax)
1<?php 2$dom = new DOMDocument(); 3$dom->resolveExternals = true; // または false 4?>
引数(parameters)
引数なし
引数はありません
戻り値(return)
bool
このプロパティは、外部リソース(DTDなど)を解決するかどうかを示します。trueであれば解決し、falseであれば解決しません。
サンプルコード
PHP DOMDocument::resolveExternals の使い方
1<?php 2 3/** 4 * Demonstrates the usage of DOMDocument::resolveExternals property. 5 * 6 * This property controls whether external entities (like DTDs or external XML entities) 7 * are resolved when parsing an XML document. 8 * 9 * - When set to `true` (default), the parser attempts to fetch and resolve external entities. 10 * This can expose the application to XML External Entity (XXE) attacks if untrusted XML is processed. 11 * - When set to `false`, external entities are ignored, which can improve security 12 * (by preventing XXE attacks) and performance if external resources are not needed. 13 * 14 * @return void 15 */ 16function demonstrateDomDocumentResolveExternals(): void 17{ 18 echo "--- Demonstrating DOMDocument::resolveExternals ---\n\n"; 19 20 // Prepare a simple XML string that references an external DTD. 21 // We'll point to a non-existent DTD (http://example.com/non-existent.dtd) 22 // to clearly show the effect of `resolveExternals` when it tries 23 // (or doesn't try) to fetch and process it. 24 $xmlStringWithExternalDtd = <<<XML 25<?xml version="1.0" encoding="UTF-8"?> 26<!DOCTYPE root SYSTEM "http://example.com/non-existent.dtd"> 27<root> 28 <item>Hello</item> 29</root> 30XML; 31 32 echo "Scenario 1: Attempting to load XML with `resolveExternals` set to FALSE.\n"; 33 echo "-------------------------------------------------------------------\n"; 34 $domFalse = new DOMDocument(); 35 36 // Set `resolveExternals` to `false` to prevent fetching external DTDs. 37 // This is often recommended for security (preventing XXE) and performance. 38 $domFalse->resolveExternals = false; 39 40 // Output the current value of the property for clarity. 41 echo " Current DOMDocument->resolveExternals: " . ($domFalse->resolveExternals ? 'true' : 'false') . "\n"; 42 43 // Attempt to load the XML. 44 // When `resolveExternals` is `false`, the parser will ignore the external DTD reference 45 // and should parse the internal XML content without issues related to external resources. 46 // `LIBXML_NOENT` is used to indicate that entities should be expanded, 47 // but with `resolveExternals=false`, external entities won't be resolved anyway. 48 $isLoadedFalse = $domFalse->loadXML($xmlStringWithExternalDtd, LIBXML_NOENT); 49 50 if ($isLoadedFalse) { 51 echo " SUCCESS: XML loaded successfully. External DTD resolution was skipped.\n"; 52 echo " Root element tag name: " . $domFalse->documentElement->tagName . "\n"; 53 } else { 54 // This outcome is unexpected if the XML itself is well-formed. 55 echo " FAILURE: XML loading failed, even with `resolveExternals=false`. (Check XML validity).\n"; 56 } 57 echo "\n"; 58 59 60 echo "Scenario 2: Attempting to load XML with `resolveExternals` set to TRUE (default).\n"; 61 echo "-------------------------------------------------------------------\n"; 62 $domTrue = new DOMDocument(); 63 64 // `resolveExternals` is true by default, but we set it explicitly for clarity. 65 $domTrue->resolveExternals = true; 66 67 // Output the current value of the property for clarity. 68 echo " Current DOMDocument->resolveExternals: " . ($domTrue->resolveExternals ? 'true' : 'false') . "\n"; 69 70 echo " EXPECTED BEHAVIOR: PHP will attempt to fetch 'http://example.com/non-existent.dtd'.\n"; 71 echo " Since this URL doesn't exist, you will likely see warnings/errors related to\n"; 72 echo " network access or DTD not found in your console output.\n"; 73 echo " `loadXML()` will likely return `false` because of the failure to resolve the DTD.\n"; 74 75 // Attempt to load the XML. 76 // When `resolveExternals` is `true` and `LIBXML_NOENT` is used, the parser will 77 // try to fetch and process the external DTD. Since "http://example.com/non-existent.dtd" 78 // does not exist, this will lead to warnings/errors and `loadXML()` will typically fail. 79 $isLoadedTrue = $domTrue->loadXML($xmlStringWithExternalDtd, LIBXML_NOENT); 80 81 if ($isLoadedTrue) { 82 echo " SUCCESS: XML loaded, but external DTD resolution likely resulted in warnings.\n"; 83 echo " Root element tag name: " . $domTrue->documentElement->tagName . "\n"; 84 } else { 85 echo " FAILURE: XML loading failed as expected, due to inability to resolve the external DTD.\n"; 86 echo " This demonstrates that when `resolveExternals` is `true` and external resources are unreachable/invalid,\n"; 87 echo " the XML loading process can fail or produce errors.\n"; 88 } 89 echo "\n"; 90 91 echo "--- End of Demonstration ---\n"; 92} 93 94// Call the function to run the demonstration. 95// When running this code, observe your console/terminal for any warnings or errors 96// related to network access for the `resolveExternals = true` scenario. 97demonstrateDomDocumentResolveExternals();
DOMDocument::resolveExternalsプロパティは、XMLドキュメントを解析する際に、外部エンティティ(例えば、外部のDTDファイルや外部XMLエンティティ)を解決するかどうかを制御するbool型の設定です。このプロパティ自体に引数はなく、値を読み取る際には現在の設定がtrueまたはfalseとして返されます。
このプロパティをtrue(デフォルト値)に設定すると、PHPはXML内で参照されている外部リソースを解決しようと試みます。外部リソースが存在しない、またはアクセスできない場合、XMLの読み込みが失敗したり、関連する警告やエラーが発生したりする可能性があります。また、信頼できないXMLファイルを処理する際に、XML外部エンティティ(XXE)攻撃というセキュリティ上の脆弱性の原因となるリスクがあります。
一方、resolveExternalsをfalseに設定すると、PHPは外部エンティティの解決をスキップし、外部リソースへのアクセスを一切試みません。この設定は、XML外部エンティティ攻撃を防ぐセキュリティ対策として非常に有効であり、不要なネットワークアクセスを減らすことで処理のパフォーマンス向上にもつながります。
提供されたサンプルコードは、存在しない外部DTDを参照するXMLデータを使用して、このプロパティの挙動を明確に示しています。resolveExternalsがfalseの場合、外部DTDの解決をスキップしてXMLを正常に読み込めることを示し、trueの場合は外部DTDの解決を試みて失敗し、その結果XMLの読み込みも失敗する様子を実演しています。
DOMDocument::resolveExternalsプロパティは、XMLドキュメントが参照する外部エンティティ(DTDなど)を読み込むかどうかを制御します。デフォルト値はtrueですが、この設定ではXML External Entity (XXE) 攻撃のリスクが高まります。信頼できないXMLを処理する場合は、必ずfalseに設定してセキュリティを確保しましょう。falseに設定することで、外部リソースへの不要なネットワークアクセスも防げるため、XMLパース処理のパフォーマンス向上や安定化にもつながります。外部エンティティの解決に失敗すると、XMLの読み込み自体がエラーとなる場合があるので、特に注意が必要です。明示的にfalseを設定する習慣をつけ、安全に利用してください。
PHP DOMDocument::resolveExternalsを試す
1<?php 2 3/** 4 * DOMDocument::resolveExternals プロパティの動作をデモンストレーションする関数。 5 * 6 * このプロパティは、PHP が DOMDocument で XML 文書をパースする際に、 7 * 外部エンティティ(例: 外部のDTDファイル、またはその他の外部リソース)の解決を試みるかどうかを制御します。 8 * 9 * - `true` に設定すると、PHP は外部リソース(ファイル、URLなど)へのアクセスを試みます。 10 * - `false` (PHP 8 のデフォルト値) に設定すると、外部リソースの解決は行われません。 11 * 12 * セキュリティ上の理由 (XML外部エンティティ (XXE) 攻撃の防止など) から、 13 * 通常は `false` に設定しておくことが強く推奨されます。 14 */ 15function demonstrateResolveExternalsProperty(): void 16{ 17 // 外部 DTD を参照するXML文字列 18 // この DTD ファイル("non_existent_external.dtd") は実際には存在しないと仮定します。 19 // これにより、resolveExternals が true の場合に、PHP が外部リソース解決を試みて失敗する挙動を確認できます。 20 $xmlStringWithExternalDtd = <<<XML 21<?xml version="1.0"?> 22<!DOCTYPE root SYSTEM "non_existent_external.dtd"> 23<root> 24 <item>サンプルデータ</item> 25</root> 26XML; 27 28 echo "--- DOMDocument::resolveExternals プロパティの動作デモ ---" . PHP_EOL; 29 30 // libxml のエラーを内部で捕捉するように設定します。 31 // これにより、外部リソース解決が失敗した際の警告メッセージをコード内でキャッチして表示できます。 32 libxml_use_internal_errors(true); 33 34 // DOMDocument の新しいインスタンスを作成します。 35 $dom = new DOMDocument(); 36 37 // DOMDocument の初期状態での resolveExternals の値を確認します。 38 // PHP 8 では通常 `false` がデフォルト値です。 39 echo "1. DOMDocument の初期状態での resolveExternals: " 40 . ($dom->resolveExternals ? "true" : "false") . PHP_EOL; 41 42 echo PHP_EOL . "--- resolveExternals が false (デフォルト) の場合 ---" . PHP_EOL; 43 // エラーバッファをクリアしてからXMLを読み込みます。 44 libxml_clear_errors(); 45 echo "2. resolveExternals が false の状態で、外部 DTD を参照するXMLを読み込みます。" . PHP_EOL; 46 echo " (PHP は外部リソース解決を抑制するため、DTDファイルが見つからなくても警告は出にくい傾向にあります)" . PHP_EOL; 47 48 if ($dom->loadXML($xmlStringWithExternalDtd)) { 49 echo " -> XMLの読み込みは成功しました。" . PHP_EOL; 50 } else { 51 echo " -> XMLの読み込みは失敗しました。" . PHP_EOL; 52 } 53 54 // 発生したlibxmlエラー/警告を表示します。 55 $errors = libxml_get_errors(); 56 if (empty($errors)) { 57 echo " -> libxmlエラーや警告は発生しませんでした。" . PHP_EOL; 58 } else { 59 echo " -> 以下のlibxmlエラーや警告が発生しました:" . PHP_EOL; 60 foreach ($errors as $error) { 61 echo " - " . trim($error->message) . PHP_EOL; 62 } 63 } 64 65 echo PHP_EOL . "--- resolveExternals を true に設定した場合 ---" . PHP_EOL; 66 // resolveExternals プロパティを `true` に設定します。 67 // これにより、PHP は外部リソース (この場合は DTD ファイル) の解決を試みるようになります。 68 $dom->resolveExternals = true; 69 echo "3. resolveExternals を true に設定しました。" . PHP_EOL; 70 echo " 現在の resolveExternals: " . ($dom->resolveExternals ? "true" : "false") . PHP_EOL; 71 72 // エラーバッファをクリアしてから、再度XMLを読み込みます。 73 libxml_clear_errors(); 74 echo "4. resolveExternals が true の状態で、外部 DTD を参照するXMLを読み込みます。" . PHP_EOL; 75 echo " (PHP が外部リソース解決を試みるため、DTDファイルが見つからないという警告が発生するはずです)" . PHP_EOL; 76 77 if ($dom->loadXML($xmlStringWithExternalDtd)) { 78 echo " -> XMLの読み込みは成功しました。" . PHP_EOL; 79 } else { 80 echo " -> XMLの読み込みは失敗しました。" . PHP_EOL; 81 } 82 83 // 発生したlibxmlエラー/警告を表示します。 84 $errors = libxml_get_errors(); 85 if (empty($errors)) { 86 echo " -> libxmlエラーや警告は発生しませんでした。" . PHP_EOL; 87 } else { 88 echo " -> 以下のlibxmlエラーや警告が発生しました (外部DTDファイルが見つからないため):" . PHP_EOL; 89 foreach ($errors as $error) { 90 echo " - " . trim($error->message) . PHP_EOL; 91 } 92 } 93 94 // libxml のエラー報告設定を元の状態に戻します。 95 libxml_use_internal_errors(false); 96 97 echo PHP_EOL . "--- デモンストレーション終了 ---" . PHP_EOL; 98} 99 100// 関数を実行して、DOMDocument::resolveExternals の動作を確認します。 101demonstrateResolveExternalsProperty();
DOMDocument::resolveExternalsは、PHP 8のDOMDocumentクラスがXML文書を解析する際に、外部のDTDファイルや他の外部リソース(外部エンティティ)の解決を試みるかどうかを制御するブール型のプロパティです。このプロパティに引数はなく、設定に応じてtrueまたはfalseの値を持ちます。
trueに設定すると、PHPはXML文書内で参照されている外部リソースへのアクセスを試みます。例えば、サンプルコードでは存在しない外部DTDファイルを参照していますが、resolveExternalsがtrueの場合、PHPはそのDTDファイルをロードしようとします。しかし、ファイルが存在しないため、libxmlから警告が発生し、XMLの解析に影響が出る可能性があります。
一方、falseに設定すると、外部リソースの解決は行われません。PHP 8では、このプロパティのデフォルト値がfalseです。サンプルコードでは、このデフォルト値の場合、外部DTDファイルを参照していても、PHPは外部リソースへのアクセスを試みないため、警告が発生しにくいことが示されています。
このプロパティはセキュリティと密接に関係しており、XML外部エンティティ(XXE)攻撃などのリスクを回避するため、通常はfalseに設定しておくことが強く推奨されます。これは、悪意のある外部リソースがシステムにアクセスするのを防ぐためです。
「DOMDocument::resolveExternals」プロパティは、XML文書が参照する外部ファイル(外部DTDなど)をPHPが読み込むかどうかを制御します。PHP 8ではデフォルトでfalseとなっており、外部ファイルの読み込みを「しない」設定です。
このプロパティは、セキュリティ上の理由から、通常はデフォルトのfalseのままで利用することを強く推奨します。trueに設定して外部ファイルの読み込みを許可すると、XML外部エンティティ(XXE)攻撃などのセキュリティリスクにつながる可能性があるため、特別な理由がない限り変更しないよう注意が必要です。
サンプルコードでは、falseとtrueの場合で、存在しない外部DTDを参照した際のエラー挙動の違いを確認できます。libxml_use_internal_errors(true)は、警告メッセージを捕捉しプロパティの効果を明確にするために使われています。