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

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

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

作成日: 更新日:

基本的な使い方

Dom\HTMLElementクラスのpreviousElementSiblingプロパティは、現在の要素の直前の兄弟要素(element)を返します。兄弟要素とは、同じ親要素を持つ要素のことです。このプロパティは、現在の要素の直前の要素が要素ノードである場合にのみ、その要素を返します。もし直前の兄弟要素が存在しない場合、または直前の兄弟要素が要素ノードでない場合、このプロパティはnullを返します。

具体的には、HTMLドキュメント内で特定の要素を見つけ、その要素の前にある兄弟要素を取得したい場合に、このプロパティを使用します。例えば、リスト内の特定の項目(<li>要素)を選択し、その直前の項目を取得する、といった操作が可能です。

previousElementSiblingプロパティは読み取り専用であり、値を設定することはできません。このプロパティを利用することで、DOMツリーを効率的にナビゲートし、特定の要素の周辺要素を特定することができます。DOM操作を行う際に、要素間の関係性を把握し、動的にコンテンツを操作する上で重要な役割を果たします。previousElementSiblingプロパティは、JavaScriptにおけるelement.previousElementSiblingプロパティと同様の機能を提供し、PHPでDOMを扱う際の要素操作を容易にします。

構文(syntax)

1Dom\HTMLElement::$previousElementSibling;

引数(parameters)

引数なし

引数はありません

戻り値(return)

DOMElement|null

previousElementSibling プロパティは、現在の要素の直前に位置する兄弟要素(同じ親を持つ要素)を DOMElement オブジェクトとして返します。直前の兄弟要素が存在しない場合は null を返します。

サンプルコード

Dom\HTMLElement::previousElementSibling で直前の要素を取得する

1<?php
2
3/**
4 * Dom\HTMLElement::previousElementSibling の使用例。
5 *
6 * この関数は、PHP 8で導入された新しい Dom 拡張機能を使用してHTML文字列を解析し、
7 * 特定のHTML要素の直前の兄弟要素(要素ノードのみ)を取得する方法を示します。
8 * テキストノードやコメントノードはスキップされます。
9 */
10function demonstratePreviousElementSibling(): void
11{
12    // 1. サンプルとなるHTML文字列を準備します。
13    // previousElementSiblingの動作を示すために、複数の要素と異なる種類のノードを配置します。
14    $htmlString = <<<HTML
15<!DOCTYPE html>
16<html>
17<body>
18    <div id="container">
19        <!-- これはコメントノードです -->
20        <p>最初の段落</p>
21        <span class="sibling-element">直前の兄弟要素</span>
22        <strong id="targetElement">ターゲット要素</strong>
23        <span>直後の兄弟要素</span>
24    </div>
25</body>
26</html>
27HTML;
28
29    // 2. PHP 8以降の新しい Dom\Document を使用してHTMLを読み込みます。
30    $document = new Dom\Document();
31    $document->loadHTML($htmlString);
32
33    // 3. previousElementSiblingを確認したい「ターゲット要素」を取得します。
34    // id="targetElement" のstrong要素を探します。
35    // Dom\Document::getElementById は Dom\Element|null を返します。
36    // HTML要素の場合、これは Dom\HTMLElement のインスタンスであることが期待されます。
37    $targetElement = $document->getElementById('targetElement');
38
39    // ターゲット要素が見つからなかった場合のエラーハンドリング
40    if (!$targetElement) {
41        echo "エラー: 'targetElement' IDを持つ要素が見つかりませんでした。\n";
42        return;
43    }
44
45    // ターゲット要素が Dom\HTMLElement のインスタンスであることを確認します。
46    if (!($targetElement instanceof Dom\HTMLElement)) {
47        echo "エラー: ターゲット要素は Dom\\HTMLElement ではありません。\n";
48        return;
49    }
50
51    echo "ターゲット要素: <{$targetElement->tagName}>\n";
52    echo "ターゲット要素のテキストコンテンツ: \"{$targetElement->textContent}\"\n";
53
54    // 4. previousElementSibling プロパティを使用して、直前の兄弟要素を取得します。
55    // このプロパティは、要素ノードのみを考慮し、テキストノードやコメントノードは無視します。
56    // 戻り値は Dom\Element|null です。
57    $previousSibling = $targetElement->previousElementSibling;
58
59    // 5. 取得した要素が存在するかどうかを確認し、その情報を出力します。
60    if ($previousSibling) {
61        echo "\n直前の兄弟要素が見つかりました:\n";
62        echo "  タグ名: <{$previousSibling->tagName}>\n";
63        echo "  テキストコンテンツ: \"{$previousSibling->textContent}\"\n";
64        echo "  クラス名 (もしあれば): " . ($previousSibling->hasAttribute('class') ? $previousSibling->getAttribute('class') : 'なし') . "\n";
65    } else {
66        echo "\nターゲット要素の直前の兄弟要素は見つかりませんでした。\n";
67    }
68
69    echo "\n--- 別例 --- \n";
70
71    // 別例: 最初の段落要素 (<p>) の直前の兄弟要素を検索
72    // この場合、コメントノードはスキップされ、直前の要素ノードはないため null になります。
73    $firstParagraph = $document->getElementsByTagName('p')->item(0);
74    if ($firstParagraph instanceof Dom\HTMLElement) {
75        echo "最初の段落要素: <{$firstParagraph->tagName}>\n";
76        $previousSiblingOfParagraph = $firstParagraph->previousElementSibling;
77
78        if ($previousSiblingOfParagraph) {
79            echo "最初の段落要素の直前の兄弟要素: <{$previousSiblingOfParagraph->tagName}>\n";
80            echo "そのテキストコンテンツ: \"{$previousSiblingOfParagraph->textContent}\"\n";
81        } else {
82            echo "最初の段落要素の直前の兄弟要素は見つかりませんでした (コメントなどの非要素ノードはスキップされます)。\n";
83        }
84    }
85}
86
87// 関数を実行してデモンストレーションを開始します。
88demonstratePreviousElementSibling();
89

Dom\HTMLElement::previousElementSiblingは、PHP 8で導入された新しいDOM拡張機能の一部で、HTMLドキュメント内の特定のHTML要素の「直前の兄弟要素」を取得するためのプロパティです。このプロパティは、HTML構造を走査する際に、テキストノードやコメントノードといった要素ではないノードタイプを完全にスキップし、要素ノードのみを対象とする点が特徴です。

サンプルコードでは、まずHTML文字列を準備し、Dom\Documentクラスを用いて解析しています。その後、IDがtargetElementである<strong>要素を取得し、この要素の直前の兄弟要素を探すために$targetElement->previousElementSiblingを使用しています。これにより、ターゲット要素の直前に位置する<span>要素が正しく取得され、そのタグ名やテキストコンテンツが出力されます。

このプロパティは引数を持ちません。戻り値は、直前の兄弟要素ノードが存在すればDom\Elementのインスタンスを、存在しない場合や直前のノードが要素ノード以外(例えばコメントノード)である場合はnullを返します。サンプルコードの後半では、最初の<p>要素の直前にはコメントノードがありますが、previousElementSiblingはこれをスキップするためnullを返す動作も示されており、このプロパティが要素ノードのみを厳密に扱うことが確認できます。

previousElementSiblingプロパティは、直前の「要素ノード」のみを取得し、コメントやテキストノードは無視される点にご注意ください。HTML構造上すぐに前にコメントやテキストがあっても、それらはスキップされます。戻り値はDom\Element型の要素、または直前の兄弟要素が存在しない場合にnullが返されますので、利用する際には必ずnullチェックを行い、要素が見つからないケースを適切に処理してください。このプロパティはPHP 8以降で導入された新しいDom拡張機能に属しており、Dom\HTMLElementクラスのインスタンスに対して使用します。getElementByIdなどで要素を取得する際は、取得した要素が確実にDom\HTMLElementのインスタンスであるかを確認することで、より安全にコードを記述できます。

PHP Dom\HTMLElement::previousElementSiblingで直前兄弟要素を取得する

1<?php
2
3/**
4 * Dom\HTMLElement::previousElementSibling プロパティの使用方法を示す関数
5 *
6 * このプロパティは、現在の要素の直前にある兄弟要素(テキストノードやコメントノードは無視)を取得します。
7 * JavaScriptの element.previousElementSibling と同じ機能を提供します。
8 *
9 * @see https://www.php.net/manual/ja/class.dom-htmlelement.php
10 * @see https://developer.mozilla.org/ja/docs/Web/API/Element/previousElementSibling
11 */
12function demonstratePreviousElementSibling(): void
13{
14    // このサンプルコードは Dom\HTMLElement クラスを使用するため、PHP 8.2 以降が必要です。
15    if (version_compare(PHP_VERSION, '8.2.0', '<')) {
16        echo "このサンプルコードは PHP 8.2 以降のバージョンで実行してください。\n";
17        return;
18    }
19
20    // デモンストレーション用のHTMLコンテンツを作成
21    $htmlContent = <<<HTML
22<!DOCTYPE html>
23<html>
24<head><title>Previous Element Sibling Demo</title></head>
25<body>
26    <div id="container">
27        <p id="first-para">最初の段落</p>
28        <!-- これはコメントです -->
29        <span>最初のスパン</span>
30        <div class="middle-div">中間のDiv</div>
31        <p id="target-para">対象の段落</p>
32        <span>最後のスパン</span>
33        <button>ボタン</button>
34    </div>
35</body>
36</html>
37HTML;
38
39    // Dom\Document を初期化し、HTMLを読み込む
40    $document = new Dom\Document();
41    $document->loadHTML($htmlContent);
42
43    // ID 'target-para' を持つ要素を取得
44    // getElementById は Dom\Element を返すことがありますが、HTML要素であれば Dom\HTMLElement として扱えます。
45    $targetElement = $document->getElementById('target-para');
46
47    if (!$targetElement instanceof Dom\HTMLElement) {
48        echo "エラー: 'target-para' 要素が見つからないか、HTMLElementではありません。\n";
49        return;
50    }
51
52    echo "--- 対象要素: '対象の段落' (id: target-para) ---\n";
53    echo "対象要素のタグ名: " . $targetElement->tagName . "\n";
54    echo "対象要素のテキスト内容: " . trim($targetElement->textContent) . "\n\n";
55
56    // previousElementSibling プロパティを使用して、直前の兄弟要素を取得
57    // 戻り値は Dom\Element|null ですが、今回はHTML要素を想定しているため Dom\HTMLElement|null で扱います。
58    /** @var Dom\HTMLElement|null $previousSibling */
59    $previousSibling = $targetElement->previousElementSibling;
60
61    if ($previousSibling !== null) {
62        echo "検出された previousElementSibling (直前の兄弟要素):\n";
63        echo "  タグ名: " . $previousSibling->tagName . "\n";
64        echo "  ID属性: " . ($previousSibling->id ?? 'なし') . "\n";
65        echo "  クラス属性: " . ($previousSibling->className ?? 'なし') . "\n";
66        echo "  テキスト内容: " . trim($previousSibling->textContent) . "\n";
67        echo "  => この要素は 'middle-div' です。\n\n";
68    } else {
69        echo "previousElementSibling (直前の兄弟要素) は見つかりませんでした (null)。\n\n";
70    }
71
72    echo "--- 別のケース: 親要素の最初の子要素 ---\n";
73    // ID 'first-para' を持つ要素を取得(これは親要素の最初の子要素です)
74    $firstElement = $document->getElementById('first-para');
75
76    if ($firstElement instanceof Dom\HTMLElement) {
77        echo "対象要素: '最初の段落' (id: first-para)\n";
78        echo "対象要素のタグ名: " . $firstElement->tagName . "\n";
79        echo "対象要素のテキスト内容: " . trim($firstElement->textContent) . "\n\n";
80
81        /** @var Dom\HTMLElement|null $noPreviousSibling */
82        $noPreviousSibling = $firstElement->previousElementSibling;
83
84        if ($noPreviousSibling !== null) {
85            echo "検出された previousElementSibling (直前の兄弟要素):\n";
86            echo "  タグ名: " . $noPreviousSibling->tagName . "\n";
87        } else {
88            echo "previousElementSibling (直前の兄弟要素) は見つかりませんでした (null)。\n";
89            echo "これは、'最初の段落' がその親要素 (div#container) の最初の子要素であるためです。\n\n";
90        }
91    }
92}
93
94// デモンストレーション関数を実行
95demonstratePreviousElementSibling();
96
97?>

「Dom\HTMLElement::previousElementSibling」プロパティは、PHP 8.2以降で利用できるDOM操作機能の一つです。このプロパティを使用すると、特定のHTML要素の直前にある「兄弟要素」を簡単に取得できます。ここで言う兄弟要素とは、同じ親要素を持つ要素のことで、テキストノードやコメントノードは無視され、HTMLタグで囲まれた要素のみが対象となります。これは、JavaScriptにおけるelement.previousElementSiblingと全く同じ働きをします。

使用する際は、まずDom\DocumentクラスでHTMLコンテンツを読み込み、そこから目的のHTML要素をDom\HTMLElementオブジェクトとして取得します。このプロパティには引数はなく、現在の要素の直前にある兄弟要素が存在すればDOMElement型のオブジェクトを返します。多くの場合、これはDom\HTMLElementとして利用可能です。しかし、もし直前に要素が存在しない場合(例えば、その要素が親の最初の子である場合など)はnullを返します。この機能により、HTML文書内の要素間の相対的な位置関係に基づいたナビゲーションや操作が、より効率的かつ簡潔に行えるようになります。

このプロパティはPHP 8.2以降で利用できますので、実行環境のバージョンを必ず確認してください。previousElementSiblingは、現在の要素の直前にある要素ノードのみを対象とし、テキストノードやコメントノードは無視される点に注意が必要です。直前の兄弟要素が存在しない場合はnullを返すため、戻り値がnullでないかを確認してから操作を行ってください。また、getElementByIdなどで取得した要素が意図するHTML要素であるか、instanceof Dom\HTMLElementで確認することで、予期せぬエラーを防ぎ、安全にコードを記述できます。

関連コンテンツ

関連IT用語

関連プログラミング言語