【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で確認することで、予期せぬエラーを防ぎ、安全にコードを記述できます。