Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】Dom\HTMLElement::firstChildプロパティの使い方

firstChildプロパティの使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

firstChildプロパティは、PHPのDOM拡張機能が提供するDom\HTMLElementオブジェクトの最初の子ノードを保持するプロパティです。このプロパティは、WebページのHTML要素の階層構造、すなわちDOMツリーをプログラムから操作する際に利用されます。特定のHTML要素が持つすべての子ノードの中から、最も先頭に位置するノードを取得する目的で使用されます。

例えば、ある<div>要素内に複数の子要素やテキストが存在する場合、firstChildプロパティにアクセスすることで、その<div>要素直下の最初の子ノード(例:<p>タグの要素ノードや、空白・改行などのテキストノード)に直接アクセスできます。このプロパティはDom\Node型のオブジェクトを返しますが、対象のHTMLElementに子ノードが一つも存在しない場合はnullが返されます。

Webコンテンツの解析や動的な操作を行うWebアプリケーション開発において、DOMツリーの探索や処理の起点として非常に有用です。子ノードには要素ノードの他にテキストノードやコメントノードなど多様な種類が含まれるため、取得したノードのタイプを確認し、目的に応じた適切な処理を実装することが必要です。

構文(syntax)

1<?php
2
3// HTML文字列を準備
4$html_string = '<div id="parent"><p>First Paragraph</p><p>Second Paragraph</p></div>';
5
6// DOMDocumentオブジェクトを作成し、HTMLを読み込む
7$doc = new DOMDocument();
8$doc->loadHTML($html_string);
9
10// idが 'parent' の要素 (HTMLElement) を取得
11$element = $doc->getElementById('parent');
12
13// firstChildプロパティで、要素の最初の子ノードを取得する
14$firstChild = $element->firstChild;
15
16// 取得したノード(最初の<p>要素)のタグ名を出力する
17// 出力: p
18echo $firstChild->nodeName;
19
20?>

引数(parameters)

引数なし

引数はありません

戻り値(return)

Dom\Node|null

この firstChild プロパティは、対象となるHTMLElementの最初の子ノードを返します。子ノードが存在しない場合は null を返します。

サンプルコード

PHP Dom\HTMLElement firstChild を取得する

1<?php
2
3/**
4 * Dom\HTMLElement::firstChild プロパティの使用例を示す関数。
5 *
6 * この関数は、HTML文字列からDOM要素を読み込み、
7 * 特定の要素の firstChild プロパティにアクセスして、その結果を表示します。
8 * PHP 8ではDom\HTMLElementクラスが導入されましたが、DOMElementはHTML要素の操作にも広く使われます。
9 * Dom\HTMLElementはDOMElementを継承しているため、DOMElementのインスタンスもfirstChildプロパティを持ち、
10 * HTML要素の最初の子ノードを取得する際に同様に機能します。
11 */
12function demonstrateFirstChildProperty(): void
13{
14    // HTML文字列を定義します。
15    // このHTMLには、idが 'parent-element' のdiv要素があり、
16    // その中に複数の子要素(段落、コメント、スパン、別のdiv)が含まれています。
17    $htmlString = <<<HTML
18<!DOCTYPE html>
19<html>
20<head>
21    <title>First Child Example</title>
22</head>
23<body>
24    <div id="parent-element">
25        <p>これは最初のP要素です。</p>
26        <!-- これはコメントノードです -->
27        <span>これは2番目のSPAN要素です。</span>
28        <div>これは3番目のDIV要素です。</div>
29    </div>
30    <div id="empty-parent-element">
31        <!-- この要素は子要素を持たない -->
32    </div>
33</body>
34</html>
35HTML;
36
37    // DOMDocumentオブジェクトを作成し、HTMLを読み込みます。
38    $dom = new DOMDocument();
39    // HTMLエラーを抑制します(オプション)。
40    @$dom->loadHTML($htmlString);
41
42    // --- 親要素が子ノードを持つ場合の例 ---
43    echo "--- 親要素が子ノードを持つ場合の例 ---\n";
44
45    // idが 'parent-element' の要素を取得します。
46    // getElementById は DOMElement を返します。
47    $parentElement = $dom->getElementById('parent-element');
48
49    if ($parentElement instanceof DOMElement) {
50        echo "親要素 (ID: parent-element) のタグ名: " . $parentElement->tagName . "\n";
51
52        // firstChild プロパティにアクセスして、最初の子ノードを取得します。
53        // firstChild は Dom\Node (テキストノード、コメントノード、要素ノードなど) または null を返します。
54        // HTMLのフォーマット(インデントや改行)によっては、改行や空白がテキストノード (#text) として
55        // 最初の子ノードになることがあります。
56        $firstChild = $parentElement->firstChild;
57
58        if ($firstChild instanceof Dom\Node) {
59            echo "最初の子ノードのタイプ (nodeName): " . $firstChild->nodeName . "\n";
60            // nodeValueはノードのテキスト内容を取得します。
61            // テキストノードの場合、改行や空白が含まれることがあるため、trim()で整形して表示します。
62            echo "最初の子ノードの値 (nodeValue): '" . trim($firstChild->nodeValue) . "'\n";
63
64            // もし最初の子ノードが要素ノード (例: <p>タグ) であれば、そのタグ名も表示できます。
65            if ($firstChild instanceof DOMElement) {
66                echo "最初の子ノードがDOMElementの場合のタグ名: " . $firstChild->tagName . "\n";
67            }
68        } else {
69            echo "親要素 (ID: parent-element) に子ノードはありません。\n";
70        }
71    } else {
72        echo "ID 'parent-element' の要素が見つかりませんでした。\n";
73    }
74
75    echo "\n--- 親要素が子ノードを持たない場合の例 ---\n";
76
77    // 子要素を持たない要素の例
78    $emptyParentElement = $dom->getElementById('empty-parent-element');
79
80    if ($emptyParentElement instanceof DOMElement) {
81        echo "空の親要素 (ID: empty-parent-element) のタグ名: " . $emptyParentElement->tagName . "\n";
82
83        $firstChildOfEmpty = $emptyParentElement->firstChild;
84
85        if ($firstChildOfEmpty instanceof Dom\Node) {
86            echo "空の親要素の最初の子ノードのタイプ: " . $firstChildOfEmpty->nodeName . "\n";
87            echo "空の親要素の最初の子ノードの値: '" . trim($firstChildOfEmpty->nodeValue) . "'\n";
88        } else {
89            // 子ノードがない場合、firstChild は null を返します。
90            echo "空の親要素 (ID: empty-parent-element) に子ノードはありません。(null が返されました)\n";
91        }
92    } else {
93        echo "ID 'empty-parent-element' の要素が見つかりませんでした。\n";
94    }
95}
96
97// 上記で定義した関数を実行します。
98demonstrateFirstChildProperty();

PHP 8で導入されたDom\HTMLElement::firstChildプロパティは、HTML文書内の特定の要素が持つ最初の子ノードを取得するために使用されます。このプロパティにアクセスすると、その要素の直下にある一番最初のノードが返されます。

戻り値はDom\Node型のオブジェクト、または子ノードが存在しない場合はnullとなります。Dom\Nodeには、pタグのようなHTML要素を表す「要素ノード」、テキスト内容を表す「テキストノード」、コメントを表す「コメントノード」など、さまざまな種類があります。HTMLの整形のために挿入された改行や空白もテキストノードとして認識される場合があります。

サンプルコードでは、HTML文字列からDOM要素を読み込み、id="parent-element"を持つ要素のfirstChildプロパティを使って最初の子ノードを取得しています。これにより、改行を含むテキストノードや、pタグなどの要素ノードがどのように取得され、その種類や内容が表示されるかを確認できます。また、子ノードを持たない要素にアクセスした際には、nullが返されることも示しています。firstChildプロパティは、HTML構造をプログラムで操作する際に、要素の開始位置を特定するために役立ちます。

firstChildプロパティは、対象要素に子ノードがない場合nullを返します。そのため、必ずif ($firstChild instanceof Dom\Node)などでnullチェックを行い、安全に利用してください。HTMLのインデントや改行も「テキストノード(#text)」として認識され、最初の子ノードになることがありますので、予期せぬノードタイプに注意が必要です。取得したノードの種類はnodeNameで確認し、nodeValueで値を取得する際はtrim()で不要な空白を整形すると良いでしょう。サンプルコードで使われているDOMElementDom\HTMLElementと同様にfirstChildプロパティを持ち、HTML要素の最初の子ノードを取得できます。

PHP DOM firstChild プロパティで最初の子ノードを取得する

1<?php
2
3/**
4 * Dom\HTMLElement の firstChild プロパティの使用例を示します。
5 *
6 * この関数は、指定されたHTML文字列からDOMドキュメントを構築し、
7 * 特定のHTML要素の最初の子ノードを取得する方法をデモンストレーションします。
8 * firstChild プロパティは、要素の最初の子ノード(テキストノード、コメントノードなども含む)を返します。
9 * もし要素ノードだけが必要な場合は、firstElementChild プロパティを使用するのがより適切です。
10 */
11function demonstrateFirstChildProperty(): void
12{
13    // PHP 8 で導入された新しい DOM 拡張機能を使用します。
14    $document = new Dom\HTMLDocument();
15
16    // サンプル HTML 文字列をロードします。
17    // このHTMLは意図的に異なる子ノードの配置をしています。
18    // - exampleContainer: コメントノードが最初の子ノードになるよう配置。
19    // - anotherContainer: HTMLの整形(改行とインデント)によるテキストノードが最初の子ノードになるよう配置。
20    // - emptyContainer: 子ノードがない要素。
21    $htmlString = <<<HTML
22<html><body>
23    <div id="exampleContainer"><!-- これはコメントノードです --><p>これは最初の要素子ノードです。</p><span>これは2番目の子要素です。</span></div>
24    <div id="anotherContainer">
25        <p>直接の子要素1</p>
26        <span>直接の子要素2</span>
27    </div>
28    <div id="emptyContainer"></div>
29</body></html>
30HTML;
31
32    // HTML文字列をDOMドキュメントに読み込みます。
33    $document->loadHTML($htmlString);
34
35    echo "--- ID 'exampleContainer' の firstChild プロパティの確認 ---\n";
36
37    // IDが 'exampleContainer' の要素を取得します。
38    $container1 = $document->getElementById('exampleContainer');
39
40    if ($container1 instanceof Dom\HTMLElement) {
41        // 'exampleContainer' の firstChild プロパティにアクセスします。
42        // 上記のHTML構造では、'<div id="exampleContainer">' の直後に
43        // '<!-- これはコメントノードです -->' が続くため、これが最初のノードになります。
44        $firstChild1 = $container1->firstChild;
45
46        if ($firstChild1 !== null) {
47            echo " 'exampleContainer' の最初の直接の子ノードが見つかりました。\n";
48            echo "  ノードタイプ: " . Dom\Node::nodeTypeToString($firstChild1->nodeType) . " ({$firstChild1->nodeType})\n";
49            echo "  ノード名: " . $firstChild1->nodeName . "\n";
50
51            // ノードタイプに応じて詳細情報を表示します。
52            if ($firstChild1 instanceof Dom\Text) {
53                echo "  ノード値 (整形済): '" . trim($firstChild1->nodeValue) . "'\n";
54            } elseif ($firstChild1 instanceof Dom\Comment) {
55                echo "  コメント内容: '" . $firstChild1->data . "'\n";
56            } elseif ($firstChild1 instanceof Dom\HTMLElement) {
57                echo "  タグ名: " . $firstChild1->tagName . "\n";
58                echo "  ノード値 (整形済): '" . trim($firstChild1->nodeValue) . "'\n";
59            } else {
60                echo "  ノード値 (整形済): '" . trim($firstChild1->nodeValue) . "'\n";
61            }
62        } else {
63            echo " 'exampleContainer' に子ノードはありませんでした。\n";
64        }
65    } else {
66        echo "ID 'exampleContainer' の要素が見つかりませんでした。\n";
67    }
68
69    echo "\n--- ID 'anotherContainer' の firstChild プロパティの確認 ---\n";
70
71    // こちらはHTMLのインデントによるテキストノードの例を示します。
72    $container2 = $document->getElementById('anotherContainer');
73    if ($container2 instanceof Dom\HTMLElement) {
74        // '<div id="anotherContainer">' の直後の改行とインデントがテキストノードとして扱われ、
75        // これが firstChild となります。
76        $firstChild2 = $container2->firstChild;
77        if ($firstChild2 !== null) {
78            echo " 'anotherContainer' の最初の直接の子ノードが見つかりました。\n";
79            echo "  ノードタイプ: " . Dom\Node::nodeTypeToString($firstChild2->nodeType) . " ({$firstChild2->nodeType})\n";
80            echo "  ノード名: " . $firstChild2->nodeName . "\n";
81            // この場合、ノード値は改行と空白文字のみになるため、trim() すると空文字列になります。
82            echo "  ノード値 (整形済): '" . trim($firstChild2->nodeValue) . "'\n";
83        } else {
84            echo " 'anotherContainer' に子ノードはありませんでした。\n";
85        }
86    } else {
87        echo "ID 'anotherContainer' の要素が見つかりませんでした。\n";
88    }
89
90    echo "\n--- ID 'emptyContainer' の firstChild プロパティの確認 ---\n";
91
92    // IDが 'emptyContainer' の要素を取得します。(子ノードがない場合)
93    $emptyContainer = $document->getElementById('emptyContainer');
94
95    if ($emptyContainer instanceof Dom\HTMLElement) {
96        // 'emptyContainer' には子ノードがないため、firstChild は null を返します。
97        $emptyFirstChild = $emptyContainer->firstChild;
98
99        if ($emptyFirstChild !== null) {
100            echo " 'emptyContainer' の最初の子ノードが見つかりました (予期しない)。\n";
101            echo "  ノードタイプ: " . Dom\Node::nodeTypeToString($emptyFirstChild->nodeType) . "\n";
102        } else {
103            echo " 'emptyContainer' に子ノードはありませんでした (期待通り)。\n";
104        }
105    } else {
106        echo "ID 'emptyContainer' の要素が見つかりませんでした。\n";
107    }
108}
109
110// 関数の実行
111demonstrateFirstChildProperty();
112

PHP 8の新しいDOM拡張機能におけるDom\HTMLElementクラスのfirstChildプロパティは、HTML要素の直下にある最初の子ノードを取得するために使用されます。このプロパティは引数を取らず、戻り値としてDom\Nodeオブジェクト、または子ノードが存在しない場合はnullを返します。

サンプルコードでは、まず指定されたHTML文字列をDOMドキュメントとして読み込み、いくつかの異なる状況でfirstChildプロパティの挙動をデモンストレーションしています。firstChildプロパティは、要素ノードだけでなく、コメントノードや、HTMLの整形による改行・インデントなどのテキストノードも対象とします。

例えば、exampleContainerのケースでは、最初に配置されたコメントノードがfirstChildとして取得されることを示しています。また、anotherContainerのケースでは、開始タグ直後の改行とインデントがテキストノードとして認識され、それがfirstChildとなることがわかります。子ノードが一つもないemptyContainerの場合には、firstChildnullを返します。

このようにfirstChildはあらゆる種類の子ノードを対象とするため、もし最初の子要素ノード(タグで囲まれたノード)のみが必要な場合は、firstElementChildプロパティを使用するのがより適切です。このプロパティを理解することで、HTML構造を正確に解析し、目的のノードにアクセスする基本的な方法を学ぶことができます。

Dom\HTMLElementfirstChildプロパティは、対象要素の「すべての種類」の最初の子ノードを返します。これには、HTMLの整形による改行やインデントといったテキストノード、コメントノードなども含まれるため、HTML要素の子ノードだけを期待すると意図しない結果になることがあります。もしHTML要素の子ノードのみを取得したい場合は、firstElementChildプロパティを使用するのが適切です。また、対象の要素に子ノードが一つも存在しない場合、firstChildnullを返します。そのため、プロパティを使用する前には必ずnullチェックを行い、エラーを防ぐようにしてください。このサンプルコードは、PHP 8で導入された新しいDOM拡張機能に基づいています。

関連コンテンツ

関連プログラミング言語

【PHP8.x】Dom\HTMLElement::firstChildプロパティの使い方 | いっしー@Webエンジニア