【PHP8.x】querySelectorメソッドの使い方

querySelectorメソッドの使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

querySelectorメソッドは、HTMLドキュメント内で指定されたCSSセレクターに一致する最初の要素を見つけ出すメソッドです。このメソッドは、PHPのDom\HTMLDocumentクラスの一部として提供され、ウェブページのような構造化されたHTMLコンテンツをプログラムで解析し、特定の情報にアクセスするために利用されます。

システムエンジニアを目指す初心者の方にとって、ウェブサイトから特定のデータを取り出したり、動的にコンテンツを操作したりする際に、この機能は非常に重要です。例えば、とあるウェブページから特定の記事のタイトルだけを取得したい場合や、フォームの入力欄にアクセスして値を設定したい場合などに役立ちます。

CSSセレクターとは、ウェブページのデザインを記述するCSSで要素を指定する際に用いる文法と同じものです。これにより、要素のID(例: #myId)、クラス(例: .myClass)、タグ名(例: div)、属性(例: [name="username"])など、様々な条件で対象の要素を正確に特定できます。

querySelectorメソッドは、指定されたセレクターに合致する要素が複数存在する場合でも、ドキュメントの読み込み順で最初に見つかった要素だけを返します。見つかった要素はDom\Elementクラスのオブジェクトとして返され、その要素に対してさらに属性の取得や内容の変更といった操作を行うことができます。もし、指定したセレクターに一致する要素がドキュメント内に一つも見つからなかった場合は、nullが返されます。このメソッドを使うことで、HTMLドキュメントの構造を理解し、目的の要素を効率的に操作できるようになります。

構文(syntax)

1<?php
2
3$htmlDocument = new Dom\HTMLDocument();
4$htmlDocument->loadHTML('<html><body><div id="unique-id"></div></body></html>');
5
6$firstMatchingElement = $htmlDocument->querySelector('#unique-id');
7
8?>

引数(parameters)

string $selectors

  • string $selectors: 検索したいCSSセレクターを指定する文字列

戻り値(return)

?Dom\Element

DOMツリーの中から、指定されたCSSセレクタに一致する最初の要素を返します。一致する要素がない場合は null を返します。

サンプルコード

PHP DomDocument: querySelectorで要素を検索する

1<?php
2
3use Dom\HTMLDocument;
4use Dom\Element;
5use Dom\NodeList;
6
7/**
8 * HTML文字列からCSSセレクタを使用して要素を検索するサンプル関数です。
9 * Dom\HTMLDocument::querySelector と Dom\HTMLDocument::querySelectorAll の両方の使用例を示します。
10 *
11 * @param string $html 対象のHTML文字列
12 * @return void
13 */
14function searchHtmlElements(string $html): void
15{
16    // 新しい Dom\HTMLDocument オブジェクトを作成します。
17    // PHP 8以降で導入されたDOM拡張のクラスです。
18    $document = new HTMLDocument();
19
20    // HTML文字列をロードします。エラーが発生した場合は終了します。
21    // loadHTML() は処理に失敗した場合 false を返すことがあります。
22    if (!$document->loadHTML($html)) {
23        echo "エラー: HTMLのロードに失敗しました。\n";
24        return;
25    }
26
27    echo "--- Dom\\HTMLDocument::querySelector の使用例 (最初の要素を検索) ---\n";
28
29    // querySelector は、指定されたCSSセレクタにマッチする「最初の」Dom\Elementを返します。
30    // マッチする要素がない場合は null を返します。
31    $firstParagraph = $document->querySelector('p');
32
33    if ($firstParagraph instanceof Element) {
34        echo "最初の <p> タグの内容: " . $firstParagraph->textContent . "\n";
35        echo "  - クラス属性: " . ($firstParagraph->getAttribute('class') ?: 'なし') . "\n";
36    } else {
37        echo "セレクタ 'p' にマッチするパラグラフは見つかりませんでした。\n";
38    }
39
40    echo "\n--- Dom\\HTMLDocument::querySelectorAll の使用例 (すべての要素を検索) ---\n";
41
42    // querySelectorAll は、指定されたCSSセレクタにマッチする「すべての」Dom\Elementを含む Dom\NodeList を返します。
43    // マッチする要素がない場合、空の NodeList を返します。
44    $allIntroParagraphs = $document->querySelectorAll('p.intro');
45
46    if ($allIntroParagraphs->count() > 0) {
47        echo "クラス 'intro' を持つすべての <p> タグが見つかりました (" . $allIntroParagraphs->count() . "個):\n";
48        // NodeList は Traversable インターフェースを実装しているため、foreach で反復処理できます。
49        foreach ($allIntroParagraphs as $index => $paragraph) {
50            // NodeList の各要素は Dom\Element 型であることを期待できます。
51            if ($paragraph instanceof Element) {
52                echo "  - #" . ($index + 1) . ": " . $paragraph->textContent . "\n";
53            }
54        }
55    } else {
56        echo "セレクタ 'p.intro' にマッチするパラグラフは見つかりませんでした。\n";
57    }
58
59    echo "\n--- 存在しないセレクタの例 ---\n";
60    $nonExistent = $document->querySelector('div.non-existent-class');
61    if ($nonExistent === null) {
62        echo "セレクタ 'div.non-existent-class' にマッチする要素は見つかりませんでした。\n";
63    }
64}
65
66// サンプルとなるHTML文字列
67$sampleHtml = <<<HTML
68<!DOCTYPE html>
69<html>
70<head>
71    <title>PHP DOM セレクタの例</title>
72</head>
73<body>
74    <h1 id="main-title">DOM操作の基本</h1>
75    <p class="intro">これは最初の紹介文のパラグラフです。</p>
76    <p>これは一般的な内容のパラグラフです。</p>
77    <p class="intro highlight">これは2番目の紹介文で、重要な情報を含みます。</p>
78    <div>
79        <ul>
80            <li>リストアイテム1</li>
81            <li>リストアイテム2</li>
82        </ul>
83    </div>
84</body>
85</html>
86HTML;
87
88// サンプル関数を実行します。
89searchHtmlElements($sampleHtml);
90
91?>

PHP 8で導入されたDom\HTMLDocumentクラスは、HTML文書をオブジェクトとして扱い、その内容をプログラムから操作するための機能を提供します。このクラスのquerySelectorメソッドは、CSSセレクタを使用してHTML文書内から特定の要素を検索する際に利用されます。

引数string $selectorsには、検索したい要素を特定するためのCSSセレクタ文字列を指定します。例えば、「p」を指定すればすべてのパラグラフの中から、「p.intro」を指定すればクラス名が「intro」のパラグラフの中から、要素を検索します。このメソッドは、指定されたセレクタにマッチする要素が最初に見つかった場合のみ、その要素を表すDom\Elementオブジェクトを返します。もしマッチする要素が一つもなかった場合はnullを返します。

サンプルコードでは、最初の<p>タグの内容を取得する例や、存在しないセレクタでnullが返される例が示されています。

なお、サンプルコードにも含まれるquerySelectorAllメソッドは、指定されたCSSセレクタにマッチするすべての要素を検索し、それらをDom\NodeListオブジェクトとして返します。querySelectorは単一の要素にアクセスする場合に、querySelectorAllは複数の要素をまとめて処理する場合に使い分けられます。これらのメソッドは、ウェブスクレイピングやHTMLコンテンツの動的な解析などで、HTML要素を効率的に特定し、操作するために活用されます。

このサンプルコードは、PHP 8で導入された新しいDOM拡張クラスを使用してHTML要素を検索する方法を示しています。querySelectorは指定したCSSセレクタに合致する「最初の要素」のみを返すため、要素が見つからない場合はnullを返す点に注意し、必ずnullチェックを行ってください。一方、querySelectorAllは合致する「すべての要素」をDom\NodeListとして返します。要素が見つからなくても空のNodeListを返すためnullチェックは不要ですが、count()で要素数を確かめ、foreachで安全に反復処理することが推奨されます。また、loadHTML()はHTMLの解析に失敗した場合にfalseを返すことがあるため、戻り値の確認も忘れないでください。これらの点に注意することで、安定したDOM操作が可能です。

PHP 8 DOM拡張: querySelectorでHTML要素を取得する

1<?php
2
3// Dom\HTMLDocument::querySelectorAll メソッドの使用例
4// このコードはPHP 8以降で利用可能な新しいDOM拡張APIを使用しています。
5// Dom\HTMLDocument::querySelector も含め、CSSセレクタを使用してHTML要素を選択します。
6
7function demonstrateDomSelectors(): void
8{
9    // 処理対象のHTMLコンテンツを定義します。
10    // 単体で動作可能にするため、内部にHTML文字列を保持します。
11    $htmlContent = <<<HTML
12<!DOCTYPE html>
13<html>
14<head>
15    <title>サンプルページ</title>
16    <link rel="stylesheet" href="style.css">
17</head>
18<body>
19    <h1>歓迎!</h1>
20    <div id="main-content">
21        <p class="highlight">これは重要な段落です。</p>
22        <p>これは通常の段落です。</p>
23        <ul class="item-list">
24            <li class="item active" data-id="1">アイテムA</li>
25            <li class="item" data-id="2">アイテムB</li>
26            <li class="item active" data-id="3">アイテムC</li>
27        </ul>
28        <a href="/about" class="button">詳細はこちら</a>
29    </div>
30    <div class="footer">
31        <p>&copy; 2023 サンプルサイト</p>
32    </div>
33</body>
34</html>
35HTML;
36
37    // Dom\HTMLDocument オブジェクトを作成し、HTMLをロードします。
38    // これにより、HTMLコンテンツをDOMツリーとして扱えるようになります。
39    $document = new Dom\HTMLDocument();
40    $document->loadHTML($htmlContent);
41
42    echo "--- '.item' クラスを持つすべてのリストアイテムを取得 ---" . PHP_EOL;
43    // Dom\HTMLDocument::querySelectorAll は、指定されたCSSセレクタに一致するすべての要素を検索し、
44    // Dom\NodeList オブジェクトとして返します。これは複数の要素を扱う際に非常に便利です。
45    $items = $document->querySelectorAll('.item');
46
47    // 取得した要素のリストをループ処理し、それぞれの要素から情報を抽出します。
48    if ($items->count() > 0) {
49        foreach ($items as $index => $item) {
50            // 各要素は Dom\Element のインスタンスです。
51            if ($item instanceof Dom\Element) {
52                echo "リストアイテム #" . ($index + 1) . ": " . $item->textContent . PHP_EOL;
53                // 'active' クラスを持っているか確認
54                if ($item->classList->contains('active')) {
55                    echo "  - このアイテムは 'active' クラスを持っています。" . PHP_EOL;
56                }
57                // 'data-id' 属性の値を取得
58                if ($item->hasAttribute('data-id')) {
59                    echo "  - Data ID: " . $item->getAttribute('data-id') . PHP_EOL;
60                }
61            }
62        }
63    } else {
64        echo "'.item' クラスを持つ要素は見つかりませんでした。" . PHP_EOL;
65    }
66
67    echo PHP_EOL . "--- '#main-content p' セレクタで、メインコンテンツ内のすべての段落を取得 ---" . PHP_EOL;
68    // 複合セレクタを使用することで、より特定の要素を選択できます。
69    $paragraphsInMainContent = $document->querySelectorAll('#main-content p');
70    if ($paragraphsInMainContent->count() > 0) {
71        foreach ($paragraphsInMainContent as $index => $paragraph) {
72            if ($paragraph instanceof Dom\Element) {
73                echo "メインコンテンツの段落 #" . ($index + 1) . ": " . $paragraph->textContent . PHP_EOL;
74            }
75        }
76    } else {
77        echo "メインコンテンツ内の段落は見つかりませんでした。" . PHP_EOL;
78    }
79
80    echo PHP_EOL . "--- 注意: 単一要素の取得には querySelector を使用 ---" . PHP_EOL;
81    // 参考情報として、Dom\HTMLDocument::querySelector メソッドの使い方も示します。
82    // querySelector は、指定されたCSSセレクタに一致する最初の要素のみを返します。
83    // 一致する要素がない場合は null を返します。
84    $firstHighlight = $document->querySelector('p.highlight');
85    if ($firstHighlight) {
86        echo "querySelector で取得した最初のハイライト段落: " . $firstHighlight->textContent . PHP_EOL;
87    } else {
88        echo "'p.highlight' に一致する要素は見つかりませんでした。" . PHP_EOL;
89    }
90
91    // IDセレクタもよく使用されます。
92    $mainContentDiv = $document->querySelector('#main-content');
93    if ($mainContentDiv) {
94        echo "querySelector で取得したIDが 'main-content' の要素: タグ名 -> " . $mainContentDiv->nodeName . PHP_EOL;
95    } else {
96        echo "IDが 'main-content' の要素は見つかりませんでした。" . PHP_EOL;
97    }
98}
99
100// 関数を実行して、セレクタの動作を確認します。
101demonstrateDomSelectors();

PHP 8で導入された新しいDOM拡張APIを使うと、HTMLコンテンツをPHPで柔軟に操作できます。特にDom\HTMLDocument::querySelectorDom\HTMLDocument::querySelectorAllメソッドは、ウェブページから特定の要素を見つける際に非常に役立ちます。これらはウェブブラウザでおなじみのCSSセレクタを使って要素を指定できるため、直感的に扱えます。

Dom\HTMLDocument::querySelectorAllメソッドは、指定されたCSSセレクタ(引数 string $selectors)に一致するすべての要素を検索し、それらをDom\NodeListオブジェクトとして返します。このDom\NodeListは、一致した複数の要素をリストとしてまとめて扱うことができる便利なコレクションです。例えば、サンプルコードでは.itemクラスを持つすべてのリストアイテムや、#main-content内にあるすべての段落を一度に取得し、それぞれのテキスト内容や属性値を取り出しています。一致する要素がない場合でも、空のDom\NodeListが返されます。

一方、Dom\HTMLDocument::querySelectorメソッドは、指定されたCSSセレクタ(引数 string $selectors)に一致する最初の要素のみを返します。このメソッドの戻り値は?Dom\Elementで、一致する要素が見つかればDom\Elementオブジェクトを、見つからなければnullを返します。サンプルコードでは、p.highlightに一致する最初の段落や、IDがmain-contentの要素を取得しています。単一の特定の要素のみを対象とする場合に適しています。

これらのメソッドを使いこなすことで、PHPでHTMLコンテンツを解析し、必要な情報を効率的に抽出する処理を容易に記述できます。

このサンプルコードはPHP 8以降で利用可能な新しいDOM拡張APIを使用しており、以前のDOM機能とは異なる点にご注意ください。querySelectorメソッドは、指定したCSSセレクタに一致する最初の要素のみを返します。要素が見つからない場合はnullを返すため、処理を行う前に必ずnullチェックを行う必要があります。一方、querySelectorAllメソッドは、一致するすべての要素をDom\NodeListオブジェクトとして返します。要素が見つからなくても空のDom\NodeListを返すため、ループ処理の前にcount()メソッドで要素の有無を確認すると安全です。引数に渡すCSSセレクタは、Webフロントエンド開発で使われるものと同じ規則で指定しますので、正確なセレクタの記述には基本的なCSSの知識が役立ちます。