【PHP8.x】specifiedプロパティの使い方
specifiedプロパティの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
specifiedプロパティは、属性が要素に実際に指定されたかどうかを示す読み取り専用のプロパティです。具体的には、Attrノードが要素ノードから取得された際に、その属性が要素の開始タグで明示的に指定されたか、またはDTD(Document Type Definition)でデフォルト値が定義されていた場合にtrueとなります。属性が要素に明示的に指定されていない場合、つまりDTDで定義されたデフォルト値のみを持つ場合はfalseを返します。このプロパティはboolean型の値を持ち、属性が要素にどのように関連付けられているかを知るために役立ちます。
例えば、HTML要素<input type="text">において、type属性は明示的に指定されているため、specifiedプロパティはtrueを返します。一方、DTDでデフォルト値が定義されている属性で、要素に明示的に記述されていない場合はfalseを返します。
このプロパティは、DOM(Document Object Model)を操作する際に、属性の扱いを決定するために重要です。属性が明示的に指定されているかどうかによって、処理を分岐させることができます。例えば、特定の属性が要素に明示的に設定されている場合にのみ、何らかの処理を実行するといったことが可能です。specifiedプロパティを使用することで、属性の存在だけでなく、その属性がどのように要素に関連付けられているかを区別し、より柔軟なDOM操作を実現できます。
構文(syntax)
1Dom\Attr::$specified;
引数(parameters)
引数なし
引数はありません
戻り値(return)
bool
このプロパティは、属性が明示的に指定されているかどうかを示す真偽値(bool)を返します。指定されていれば true、そうでなければ false となります。
サンプルコード
PHP Dom\Attrの$specifiedプロパティを判定する
1<?php 2 3/** 4 * Dom\Attrクラスの $specified プロパティの使用例です。 5 * 6 * このプロパティは、XML/HTMLの属性がソースコード内で明示的に指定されたものか (true)、 7 * それともDTD(文書型定義)などによるデフォルト値か (false) を判定するために使用します。 8 * これは、属性が「指定された」状態を詳細に知るための機能です。 9 */ 10function checkAttributeIsSpecified(): void 11{ 12 // 'type'属性にデフォルト値"default"を持つDTDを定義したXML文字列 13 $xml = <<<XML 14 <?xml version="1.0" encoding="utf-8"?> 15 <!DOCTYPE root [ 16 <!ELEMENT root (element+)> 17 <!ELEMENT element EMPTY> 18 <!ATTLIST element type CDATA "default"> 19 ]> 20 <root> 21 <!-- 1. type属性が "explicit" として明示的に指定された要素 --> 22 <element type="explicit" /> 23 <!-- 2. type属性が省略され、DTDのデフォルト値が適用される要素 --> 24 <element /> 25 </root> 26 XML; 27 28 // DOMDocumentを初期化し、DTDを解釈するように設定してXMLを読み込みます 29 $doc = new DOMDocument(); 30 $doc->validateOnParse = true; 31 $doc->loadXML($xml); 32 33 // 全ての<element>要素を取得します 34 $elements = $doc->getElementsByTagName('element'); 35 36 // 1. 明示的に指定された属性の場合 37 $explicitAttr = $elements[0]->getAttributeNode('type'); 38 echo '明示的に指定された属性 (type="explicit"):' . PHP_EOL; 39 echo ' - 値: ' . $explicitAttr->value . PHP_EOL; 40 // $specified は true を返します 41 echo ' - $specified プロパティ: ' . ($explicitAttr->specified ? 'true' : 'false') . PHP_EOL; 42 43 echo PHP_EOL; 44 45 // 2. DTDによるデフォルトの属性の場合 46 $defaultAttr = $elements[1]->getAttributeNode('type'); 47 echo 'DTDのデフォルト値が適用された属性:' . PHP_EOL; 48 echo ' - 値: ' . $defaultAttr->value . PHP_EOL; 49 // $specified は false を返します 50 echo ' - $specified プロパティ: ' . ($defaultAttr->specified ? 'true' : 'false') . PHP_EOL; 51} 52 53// 関数を実行します 54checkAttributeIsSpecified();
PHPのDom\Attrクラスに属するspecifiedプロパティは、XMLやHTMLの属性がどのように設定されたかを調べるためのものです。このプロパティは引数を取らず、戻り値としてbool型(trueまたはfalse)を返します。
このプロパティがtrueを返すのは、属性がソースコード内で明示的に記述されている場合です。一方、属性が省略され、DTD(文書型定義)などで定義されたデフォルト値が適用された場合にはfalseを返します。
サンプルコードでは、まずDTDでtype属性のデフォルト値が "default" に設定されたXML文書を作成しています。この文書内には2つの<element>要素があります。1つ目の要素はtype="explicit"と属性が明示的に指定されており、この属性のspecifiedプロパティはtrueになります。2つ目の要素はtype属性が省略されているため、DTDのデフォルト値 "default" が適用されます。この場合、属性は明示的に指定されていないため、specifiedプロパティはfalseを返します。
このようにspecifiedプロパティを使用することで、属性が開発者によって直接設定されたものか、スキーマなどによるデフォルト値なのかを正確に判別することができます。
Dom\Attrクラスのspecifiedプロパティは、属性がソースコードに直接書かれたものか、DTD等で定義されたデフォルト値かを判定します。この機能が意図通りに動作するには、DOMDocumentのvalidateOnParseプロパティをtrueに設定し、DTDを解釈させる必要があります。この設定がないと、デフォルト値が適用されず、specifiedプロパティは期待通りに機能しません。また、このプロパティは属性ノードのものです。属性値の文字列を返すgetAttribute()ではなく、属性ノードオブジェクトを返すgetAttributeNode()メソッドを使う点に注意してください。なお、一連のDOM操作は、PHP環境にphp-xml拡張モジュールがインストールされていることが前提です。
Dom\Attr->specified でタイムアウト指定を確認する
1<?php 2 3declare(strict_types=1); 4 5/** 6 * Dom\Attr->specified プロパティの使用例を示すクラス 7 * 8 * このプロパティは、属性がソースドキュメントで明示的に指定された場合に true を返します。 9 * DTDなどで定義されたデフォルト値が適用された場合は false を返します。 10 */ 11final class DomAttributeChecker 12{ 13 /** 14 * XML内の接続設定をチェックし、タイムアウト属性が明示的に指定されているかを確認します。 15 * 16 * キーワード「the timeout specified has expired」に関連付け、 17 * XML設定ファイル内の "timeout" 属性が明示的に指定されているかどうかを 18 * Dom\Attr->specified プロパティを使って検証します。 19 */ 20 public static function checkTimeoutSpecification(): void 21 { 22 // 検証対象のXML文字列 23 // 1つ目のconnectionにはtimeout属性が明示的に指定されている 24 // 2つ目のconnectionにはtimeout属性が存在しない 25 $xmlString = <<<XML 26 <?xml version="1.0" encoding="UTF-8"?> 27 <config> 28 <connection host="primary.db.example.com" timeout="30" /> 29 <connection host="secondary.db.example.com" /> 30 </config> 31 XML; 32 33 // DOMDocumentオブジェクトを生成し、XMLを読み込む 34 $doc = new \DOMDocument(); 35 $doc->loadXML($xmlString); 36 37 // 'connection' タグを持つ要素を取得する 38 $connections = $doc->getElementsByTagName('connection'); 39 40 echo "Checking for explicitly specified 'timeout' attributes..." . PHP_EOL; 41 echo "--------------------------------------------------------" . PHP_EOL; 42 43 // 各connection要素をループで調べる 44 foreach ($connections as $connection) { 45 /** @var \DOMElement $connection */ 46 $host = $connection->getAttribute('host'); 47 48 // 'timeout' 属性のノード (Dom\Attr オブジェクト) を取得する 49 // 属性が存在しない場合、getAttributeNodeは null を返す 50 $timeoutAttr = $connection->getAttributeNode('timeout'); 51 52 // 属性ノードが取得でき、かつその 'specified' プロパティが true かどうかを評価 53 if ($timeoutAttr instanceof \DOMAttr && $timeoutAttr->specified) { 54 // 属性がXML内で明示的に指定されていた場合 55 $value = $timeoutAttr->value; 56 echo "[OK] Host '{$host}': Timeout is explicitly specified with value '{$value}'." . PHP_EOL; 57 } else { 58 // 属性が指定されていなかった場合 59 echo "[INFO] Host '{$host}': Timeout is not specified; a default value might be used." . PHP_EOL; 60 } 61 } 62 } 63} 64 65// メソッドを実行して結果を確認 66DomAttributeChecker::checkTimeoutSpecification();
Dom\Attr->specifiedプロパティは、XMLやHTMLの属性がソースコード上で明示的に記述されたものかどうかを判定するためのものです。このプロパティは引数を取らず、戻り値として真偽値(bool)を返します。属性がソースに直接書かれていればtrueを、DTD(文書型定義)などで定義されたデフォルト値が適用されている場合や、属性自体が存在しない場合はfalseとなります。
このサンプルコードでは、データベース接続設定のXMLを扱っています。キーワード「the timeout specified has expired」に関連し、timeout属性が設定ファイル内で意図的に指定されたものかを検証します。
コードでは、まずXML文字列を読み込み、2つの<connection>要素を取得します。ループ処理の中で、getAttributeNode()メソッドを使って各要素からtimeout属性の情報を取得し、そのspecifiedプロパティの値を調べています。
1つ目の要素はtimeout="30"と明記されているため、specifiedプロパティはtrueを返し、「明示的に指定されている」と表示されます。一方、2つ目の要素にはtimeout属性が存在しないため、属性が指定されていないと判断されます。このように、specifiedプロパティは、属性が開発者によって直接設定された値なのかどうかを確実に判別する際に役立ちます。
getAttributeNodeメソッドは、属性が存在しない場合にnullを返すため、$timeoutAttr->specifiedのように直接プロパティへアクセスする前に、if文でオブジェクトが存在するかを必ず確認する必要があります。これを行わないとエラーの原因となります。specifiedプロパティは、XMLソースに属性が明示的に書かれているかを確認するために使います。DTD(文書型定義)などでデフォルト値が設定されている場合はfalseを返すため、単に属性の有無を確認するだけでなく、その定義元を区別する際に重要です。また、実際の開発ではloadXMLが不正なXMLを読み込んで失敗する可能性も考慮し、エラーハンドリングを行うことが推奨されます。