【PHP8.x】Dom\DocumentFragment::firstElementChildプロパティの使い方
firstElementChildプロパティの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
firstElementChildプロパティは、PHPのDOM拡張機能の一部であるDom\DocumentFragmentクラスにおいて、そのフラグメント(断片)の最初の子要素を保持するプロパティです。Dom\DocumentFragmentクラスは、Webページの一部となるHTMLやXMLの構造をメモリ上で一時的に構築し、操作するための特別なオブジェクトです。これにより、実際のドキュメントに直接変更を加えることなく、効率的にDOMツリーの断片を扱えます。
このfirstElementChildプロパティを使用すると、Dom\DocumentFragment内に含まれる多数のノードの中から、最初に見つかる「要素」(例: <div>や<p>などのタグで構成される部分)へ直接アクセスできます。ここでいう「要素」は、テキストノードやコメントノードを含まず、HTMLやXMLの構造を定義するタグ付きの要素のみを指します。
もしDom\DocumentFragment内に子要素が存在しない場合や、最初の子ノードが要素ではない(例えばテキストやコメントである)場合には、このプロパティはnullを返します。したがって、このプロパティを利用することで、動的に生成されたHTML断片の構造を効率的に走査し、特定の要素にアクセスする際に役立ちます。PHP 8以降の環境で、DOM操作を行う際に活用される重要なプロパティの一つです。
構文(syntax)
1<?php 2$document = new DOMDocument(); 3$documentFragment = $document->createDocumentFragment(); 4 5// Dom\DocumentFragment の最初の要素の子ノードにアクセス 6$firstElementChild = $documentFragment->firstElementChild; 7?>
引数(parameters)
引数なし
引数はありません
戻り値(return)
Dom\Element|null
このプロパティは、Dom\DocumentFragment オブジェクトの最初の子要素を表す Dom\Element オブジェクト、または子要素が存在しない場合は null を返します。
サンプルコード
PHP Dom\DocumentFragment firstElementChild を取得する
1<?php 2 3// Dom\DocumentFragment の firstElementChild プロパティの使用例 4// このコードは、Dom\DocumentFragment の最初の子要素ノードを取得する方法を示します。 5// firstElementChild は要素ノード(タグを持つノード)のみを対象とし、 6// テキストノードやコメントノードはスキップされます。 7 8// 1. Dom\Document インスタンスの作成 9// Dom\DocumentFragment は、通常 Dom\Document のメソッドを使って作成されます。 10$dom = new Dom\Document(); 11 12// 2. Dom\DocumentFragment の作成 13// これはHTML/XMLの断片を一時的に保持するためのコンテナです。 14$fragment = $dom->createDocumentFragment(); 15 16// 3. DocumentFragment に子ノードを追加 17// いくつかの異なる種類のノードを追加して、firstElementChild の動作を確認します。 18 19// テキストノードを追加 (firstElementChild はスキップする) 20$textNode = $dom->createTextNode("これは先頭のテキストです。"); 21$fragment->appendChild($textNode); 22 23// コメントノードを追加 (firstElementChild はスキップする) 24$commentNode = $dom->createComment("これはコメントです。"); 25$fragment->appendChild($commentNode); 26 27// 最初の要素ノードを追加 28$spanElement = $dom->createElement("span", "Hello SPAN"); 29$fragment->appendChild($spanElement); 30 31// 2番目の要素ノードを追加 32$pElement = $dom->createElement("p", "World P"); 33$fragment->appendChild($pElement); 34 35echo "--- Dom\\DocumentFragment に要素がある場合の firstElementChild ---\n"; 36 37// 4. firstElementChild プロパティへのアクセス 38// firstElementChild は、Dom\DocumentFragment 内の最初の子要素ノードを返します。 39// テキストノードやコメントノードは要素ではないためスキップされ、 40// 最初の Dom\Element オブジェクトが返されます。 41$firstElement = $fragment->firstElementChild; 42 43if ($firstElement instanceof Dom\Element) { 44 echo "取得された最初の要素のタグ名: " . $firstElement->tagName . "\n"; 45 echo "取得された最初の要素のテキストコンテンツ: " . $firstElement->textContent . "\n"; 46} else { 47 echo "この DocumentFragment には子要素が見つかりませんでした。\n"; 48} 49 50echo "\n--- Dom\\DocumentFragment に要素がない場合の firstElementChild ---\n"; 51 52// 5. 子要素がない場合の firstElementChild の動作 53// 新しい空の Dom\DocumentFragment を作成します。 54$emptyFragment = $dom->createDocumentFragment(); 55 56// 空のフラグメントでは firstElementChild は null を返します。 57$firstElementInEmpty = $emptyFragment->firstElementChild; 58 59if ($firstElementInEmpty instanceof Dom\Element) { 60 // このブロックは実行されません 61 echo "取得された最初の要素のタグ名: " . $firstElementInEmpty->tagName . "\n"; 62} else { 63 echo "この Dom\\DocumentFragment には子要素がありません(nullを返しました)。\n"; 64} 65
Dom\DocumentFragment::firstElementChildプロパティは、HTMLやXMLの構造を操作する際に用いられるDom\DocumentFragmentオブジェクトの中から、最初の子「要素ノード」を取得するために使用されます。引数はなく、戻り値はDom\Elementオブジェクト、または該当する子要素ノードが存在しない場合はnullとなります。
ここでいう「要素ノード」とは、<span>や<p>のようにタグを持つノードのことで、テキストノードやコメントノードは含まれません。firstElementChildは、Dom\DocumentFragment内の子ノードを先頭から順に走査し、テキストノードやコメントノードをスキップして、最初に見つかったDom\Elementオブジェクトを返します。
サンプルコードでは、まずDom\DocumentとDom\DocumentFragmentを作成し、テキストノード、コメントノード、そして複数の要素ノード(<span>と<p>)を追加しています。firstElementChildにアクセスすると、追加された中で最初の要素ノードである<span>要素がDom\Elementオブジェクトとして取得され、そのタグ名やテキストコンテンツを表示できます。
一方、子要素ノードが一つも含まれていないDom\DocumentFragmentに対してfirstElementChildを使用した場合、何も要素が見つからないため、戻り値はnullとなります。このプロパティを使うことで、指定されたコンテナの最初の子要素に効率的にアクセスし、操作することが可能になります。
このサンプルコードのfirstElementChildは、Dom\DocumentFragment内の最初の子「要素ノード」(タグを持つノード)のみを取得します。テキストノードやコメントノードは要素とはみなされずスキップされる点にご注意ください。また、子要素が全く存在しない場合はnullを返します。そのため、取得した結果をすぐに利用せず、if ($firstElement instanceof Dom\Element)のように、実際にDom\Elementオブジェクトであるかを確認する安全なチェックを必ず行ってください。このチェックを怠ると、nullに対してプロパティにアクセスしようとしてエラーが発生する可能性があります。Dom\DocumentFragmentは通常、Dom\Document::createDocumentFragment()メソッドを使って生成します。
firstElementChildとfirstChildを取得する
1<?php 2 3// Dom\DocumentFragment の firstElementChild プロパティの使用例 4// firstElementChild と firstChild の違いを初心者向けに示します。 5 6function demonstrateDocumentFragmentProperties(): void 7{ 8 // Dom\DocumentFragment は、DOMツリーの一部ではないノードの「コンテナ」です。 9 // これ自体は画面に表示されませんが、子ノードを一括で操作したり、文書に追加したりする際に便利です。 10 $fragment = new Dom\DocumentFragment(); 11 12 // Dom\Element や Dom\Text を作成するには、Dom\Document インスタンスが必要です。 13 $dom = new Dom\Document(); 14 15 // 1. フラグメントにノードを追加します。 16 // まず、テキストノードを追加します。これは最初の子ノード (firstChild) になります。 17 $initialTextNode = $dom->createTextNode('これは最初のテキストノードです。'); 18 $fragment->appendChild($initialTextNode); 19 20 // 次に、要素ノード (タグを持つノード) を追加します。 21 // これは最初の子要素 (firstElementChild) になります。 22 $firstDivElement = $dom->createElement('div', 'これは最初のdiv要素です。'); 23 $fragment->appendChild($firstDivElement); 24 25 // 別の要素ノードを追加します。 26 $spanElement = $dom->createElement('span', 'これは2番目の要素です。'); 27 $fragment->appendChild($spanElement); 28 29 echo "--- firstElementChild の使用 ---\n"; 30 // 2. firstElementChild プロパティを使用して、最初の子要素を取得します。 31 // firstElementChild は、要素ノード (<div>, <span>などのタグを持つノード) のみを対象とします。 32 $firstElement = $fragment->firstElementChild; 33 34 if ($firstElement instanceof Dom\Element) { 35 echo "firstElementChild は Dom\\Element です。\n"; 36 echo " タグ名: " . $firstElement->tagName . "\n"; 37 echo " 内容: " . $firstElement->textContent . "\n"; 38 } else { 39 echo "firstElementChild は null です。(フラグメント内に要素が見つかりませんでした)\n"; 40 } 41 42 echo "\n--- firstChild の使用 ---\n"; 43 // 3. firstChild プロパティを使用して、最初のすべての子ノードを取得します。 44 // firstChild は、テキストノード、要素ノード、コメントノードなど、あらゆる種類のノードを対象とします。 45 $firstNode = $fragment->firstChild; 46 47 if ($firstNode instanceof Dom\Node) { 48 echo "firstChild は Dom\\Node です。\n"; 49 echo " ノードタイプ: " . getNodeTypeName($firstNode->nodeType) . "\n"; 50 echo " 内容: " . $firstNode->textContent . "\n"; 51 if ($firstNode instanceof Dom\Element) { 52 echo " タグ名: " . $firstNode->tagName . "\n"; 53 } 54 } else { 55 echo "firstChild は null です。(フラグメント内にノードが見つかりませんでした)\n"; 56 } 57 58 echo "\n--- 比較のまとめ ---\n"; 59 echo " - firstElementChild は、最初の「要素ノード」(タグを持つノード、例: <div>)を返します。\n"; 60 echo " - firstChild は、最初の「子ノード」(要素、テキスト、コメントなど、種類を問わず)を返します。\n"; 61 echo "この例では、最初にテキストノードを追加したため、firstChild はテキストノードを返しました。\n"; 62 echo "しかし、firstElementChild はテキストノードをスキップし、最初に見つかった要素ノード (<div>) を返しました。\n"; 63} 64 65/** 66 * DOMノードタイプを分かりやすい文字列に変換するヘルパー関数。 67 */ 68function getNodeTypeName(int $nodeType): string 69{ 70 return match ($nodeType) { 71 XML_ELEMENT_NODE => 'ELEMENT_NODE (要素)', 72 XML_ATTRIBUTE_NODE => 'ATTRIBUTE_NODE (属性)', 73 XML_TEXT_NODE => 'TEXT_NODE (テキスト)', 74 XML_CDATA_SECTION_NODE => 'CDATA_SECTION_NODE (CDATAセクション)', 75 XML_ENTITY_REF_NODE => 'ENTITY_REF_NODE (実体参照)', 76 XML_ENTITY_NODE => 'ENTITY_NODE (実体)', 77 XML_PI_NODE => 'PI_NODE (処理命令)', 78 XML_COMMENT_NODE => 'COMMENT_NODE (コメント)', 79 XML_DOCUMENT_NODE => 'DOCUMENT_NODE (ドキュメント)', 80 XML_DOCUMENT_TYPE_NODE => 'DOCUMENT_TYPE_NODE (ドキュメントタイプ)', 81 XML_DOCUMENT_FRAG_NODE => 'DOCUMENT_FRAGMENT_NODE (ドキュメントフラグメント)', 82 XML_NOTATION_NODE => 'NOTATION_NODE (表記)', 83 default => 'UNKNOWN_NODE (不明なノード)', 84 }; 85} 86 87// サンプルコードを実行します。 88demonstrateDocumentFragmentProperties(); 89 90?>
PHP 8のDom\DocumentFragmentクラスが持つfirstElementChildプロパティは、HTMLやXMLの構造をプログラムで操作する際に利用されるオブジェクトであるDom\DocumentFragmentの、最初の子「要素ノード」を取得するために使用されます。このプロパティに引数はなく、戻り値は最初に見つかったDom\Element型のインスタンスとなります。もし要素ノードが存在しない場合はnullを返します。
Dom\DocumentFragmentは、メモリ上で一時的にDOMノードを格納し、まとめて操作したり、実際の文書に追加したりするのに便利なコンテナです。このfirstElementChildプロパティは、同様に最初の子ノードを取得するfirstChildプロパティとよく比較されます。
主な違いとして、firstElementChildは<div>や<span>のようなタグを持つ「要素ノード」のみを対象とします。一方、firstChildは要素ノードだけでなく、テキストノードやコメントノードなど、あらゆる種類の最初の子ノードを返します。サンプルコードでは、フラグメントにテキストノードの後にdiv要素を追加しています。この場合、firstChildは最初に追加されたテキストノードを返しますが、firstElementChildはテキストノードをスキップし、最初に見つかる要素ノードであるdiv要素を返します。このように、目的の子ノードが要素であるか、それとも種類を問わないかで使い分けることが重要です。
Dom\DocumentFragmentのfirstElementChildプロパティは、フラグメント内の最初の子要素ノード(タグを持つノード)のみを返します。これに対し、firstChildプロパティは、テキストノードやコメントノードを含む、最初の子ノード全てを返します。この両者の違いを理解せず使用すると、期待と異なるノードを取得する可能性があります。
いずれのプロパティも、該当する子ノードが存在しない場合はnullを返します。そのため、取得した値がnullでないか、そして期待するDom\Element型であるかなどを、if ($element instanceof Dom\Element)のように確認してから利用することが重要です。Dom\DocumentFragmentはDOMツリーに直接追加される前のノードの一時的なコンテナであり、ノード自体はDom\Documentインスタンスを使って作成します。