【PHP8.x】bodyプロパティの使い方

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

作成日: 更新日:

基本的な使い方

bodyプロパティは、PHPのDom\HTMLDocumentクラスにおいて、HTMLドキュメントの主要なコンテンツ領域である<body>要素を保持するプロパティです。

Dom\HTMLDocumentクラスは、HTMLドキュメント全体の構造をオブジェクトとして表現し、プログラムからその内容や構造を操作できるようにするためのものです。HTMLドキュメントの実際のコンテンツ、例えばテキスト、画像、リンクなどは、すべて<body>要素の中に記述されます。

このbodyプロパティを利用することで、HTMLドキュメントの本体部分に直接アクセスし、その内容をプログラムから読み取ったり、新しい要素を追加したり、既存の要素の属性やテキストを変更・削除したりといったDOM(Document Object Model)操作を行うことが可能になります。

具体的には、このプロパティにアクセスすると、HTMLの<body>要素を表現するDom\HTMLElement型のオブジェクトが返されます。これにより、サーバーサイドでHTMLコンテンツを動的に生成したり、既存のHTMLファイルを解析して特定の情報を抽出したり、構造を編集したりする際に、<body>要素を起点として詳細な操作を行うことができます。

ウェブページのコンテンツをプログラムで操作する上で、このbodyプロパティはDOM操作の基本的な出発点として非常に重要な役割を果たします。

構文(syntax)

1<?php
2
3$htmlDocument = new Dom\HTMLDocument();
4$htmlDocument->loadHTML('<!DOCTYPE html><html><body></body></html>');
5
6$bodyElement = $htmlDocument->body;
7
8?>

引数(parameters)

引数なし

引数はありません

戻り値(return)

Dom\Element

Dom\HTMLDocument クラスの body プロパティは、HTMLドキュメントの <body> 要素を表す Dom\Element オブジェクトを返します。

サンプルコード

PHPでbodyクラスを追加する

1<?php
2
3declare(strict_types=1);
4
5/**
6 * HTML文字列を受け取り、そのbodyタグに新しいCSSクラスを追加します。
7 * これはWordPressの body_class() 関数の基本的な動作を模倣したものです。
8 *
9 * @param string $htmlContent 元となるHTMLコンテンツの文字列。
10 * @param string $classToAdd  bodyタグに追加したいクラス名。
11 * @return string             クラスが追加された新しいHTML文字列。
12 */
13function addClassToBody(string $htmlContent, string $classToAdd): string
14{
15    // Dom\HTMLDocument オブジェクトを生成します。
16    // PHP 8.2で導入された新しいDOM拡張機能です。
17    $doc = new Dom\HTMLDocument();
18
19    // HTML文字列をドキュメントに読み込みます。
20    $doc->loadHTML($htmlContent);
21
22    // 'body' プロパティを使って <body> 要素 (Dom\Element) を直接取得します。
23    // HTMLに<body>タグが存在しない場合は null になります。
24    $bodyElement = $doc->body;
25
26    // body要素が正常に取得できたかを確認します。
27    if ($bodyElement !== null) {
28        // 既存のclass属性の値を取得します。存在しない場合は空文字列になります。
29        $existingClasses = $bodyElement->getAttribute('class') ?? '';
30
31        // 既存のクラスと新しいクラスを結合します。
32        // すでに同じクラスが存在する場合の重複を避けるため、一度配列に変換します。
33        $classList = explode(' ', $existingClasses);
34        $classList[] = $classToAdd;
35
36        // 配列から重複する値と空の値を削除します。
37        $uniqueClasses = array_filter(array_unique($classList));
38        
39        // 配列をスペース区切りの文字列に戻します。
40        $newClasses = implode(' ', $uniqueClasses);
41
42        // setAttribute() メソッドで、更新したclass属性をbody要素に設定します。
43        $bodyElement->setAttribute('class', $newClasses);
44    }
45
46    // 変更が適用されたHTML全体を文字列として返します。
47    return $doc->saveHTML();
48}
49
50// --- サンプル実行 ---
51
52// 操作対象のHTML文字列を定義
53$originalHtml = <<<HTML
54<!DOCTYPE html>
55<html lang="ja">
56<head>
57    <title>サンプルページ</title>
58</head>
59<body class="home page-template">
60    <h1>ようこそ!</h1>
61    <p>これはサンプルコンテンツです。</p>
62</body>
63</html>
64HTML;
65
66// bodyタグに追加したいクラス名
67$newClass = 'user-logged-in';
68
69// 関数を呼び出してHTMLを更新
70$modifiedHtml = addClassToBody($originalHtml, $newClass);
71
72// 結果を出力
73echo $modifiedHtml;
74
75?>

このサンプルコードは、PHPのDom\HTMLDocumentクラスを利用して、HTML文字列の<body>タグに新しいCSSクラスを追加する関数 addClassToBody() を実装したものです。この関数は、WordPressの body_class() 関数の動作を模倣しています。

addClassToBody() 関数は、HTMLコンテンツの文字列 $htmlContent と、追加したいクラス名 $classToAdd を引数として受け取ります。まず、Dom\HTMLDocument オブジェクトを生成し、loadHTML() メソッドでHTML文字列を読み込みます。$doc->body を使用して、<body> 要素を Dom\Element オブジェクトとして直接取得します。もし <body> タグが存在しない場合は null が返されます。

<body> 要素が存在する場合、既存の class 属性の値を取得し、新しいクラス名と結合します。重複を避けるため、クラス名を一度配列に変換し、重複を取り除いた後、再びスペース区切りの文字列に戻します。そして、setAttribute() メソッドを使って、更新された class 属性を <body> 要素に設定します。最後に、変更が適用されたHTML全体を文字列として返します。

サンプル実行部分では、HTML文字列と追加するクラス名を定義し、addClassToBody() 関数を呼び出してHTMLを更新しています。結果として、<body> タグに新しいクラスが追加されたHTMLが出力されます。この例では、home page-template という既存のクラスを持つ <body> タグに user-logged-in というクラスが追加されます。Dom\HTMLDocument クラスの body プロパティを利用することで、<body> 要素へのアクセスが容易になります。

このサンプルコードは、HTMLの<body>タグにクラスを追加する関数addClassToBody()を実装しています。Dom\HTMLDocumentはPHP 8以降で使用可能なクラスです。古いPHPバージョンでは動作しません。$doc->body<body>要素を取得しますが、HTMLに<body>タグがない場合はnullが返る点に注意が必要です。getAttribute('class') ?? ''は、class属性が存在しない場合に空文字列を返すための構文です。array_unique()でクラス名の重複を避けていますが、複雑なHTML構造では期待通りに動作しない可能性があります。saveHTML()はHTML全体を返すため、不要なDOCTYPE宣言などが追加される場合があります。セキュリティ対策として、HTMLを外部から受け取る場合は、必ずエスケープ処理を行ってください。

PHPでHTMLのbody要素を取得する

1<?php
2
3// HTML ドキュメントをロードし、body 要素を取得する例
4function getBodyElement(string $html): ?DOMElement
5{
6    $dom = new DOMDocument();
7
8    // HTML の読み込みでエラーが発生した場合でも処理を継続する
9    libxml_use_internal_errors(true);
10    $dom->loadHTML($html);
11    libxml_clear_errors();
12
13    // body 要素を取得
14    return $dom->getElementsByTagName('body')->item(0);
15}
16
17// HTML 文字列の例
18$htmlContent = <<<HTML
19<!DOCTYPE html>
20<html>
21<head>
22    <title>Example</title>
23</head>
24<body>
25    <h1>Hello, world!</h1>
26    <p>This is a paragraph.</p>
27</body>
28</html>
29HTML;
30
31// body 要素を取得
32$bodyElement = getBodyElement($htmlContent);
33
34// body 要素が存在する場合、内容を出力
35if ($bodyElement !== null) {
36    echo $bodyElement->nodeValue . PHP_EOL; // "Hello, world! This is a paragraph." が出力される
37} else {
38    echo "Body element not found." . PHP_EOL;
39}
40

このサンプルコードは、PHPのDOMDocumentクラスを使用して、HTMLドキュメントから<body>要素を取得する方法を示しています。getBodyElement関数は、HTML文字列を引数として受け取り、DOMDocumentオブジェクトを生成します。loadHTMLメソッドを使用してHTMLを読み込みます。libxml_use_internal_errors(true)libxml_clear_errors()を使用することで、HTMLの読み込み時にエラーが発生した場合でも処理を継続できます。

getElementsByTagName('body')メソッドは、<body>タグを持つすべての要素を含むDOMNodeListを返します。item(0)メソッドを使用して、最初の<body>要素を取得します。もし<body>要素が存在しない場合は、nullを返します。

メイン部分では、サンプルHTML文字列が定義され、getBodyElement関数に渡されます。取得した<body>要素がnullでない場合、nodeValueプロパティを使用して<body>要素内のテキストコンテンツを出力します。nodeValueプロパティは、要素とそのすべての子孫ノードのテキストコンテンツを結合したものを返します。もし<body>要素が見つからない場合は、「Body element not found.」というメッセージが出力されます。

このコードは、WebスクレイピングやHTML解析を行う際の基本的な処理を理解するのに役立ちます。特に、HTML構造をプログラムで操作し、特定の要素の内容を取得したい場合に有用です。DOMDocumentクラスは、複雑なHTML構造を扱うための強力なツールを提供します。

Dom\HTMLDocument->body プロパティ(ここでは getElementsByTagName('body') で代替)を利用する際の注意点です。まず、HTMLの読み込み時にエラーが発生する可能性があるため、libxml_use_internal_errors(true) でエラーを抑制し、libxml_clear_errors() でエラーをクリアしています。これは、HTMLの構造が正しくない場合でも、スクリプトが停止しないようにするためです。getElementsByTagName('body')->item(0) は、HTMLドキュメント内の最初の body 要素を取得します。もし body 要素が存在しない場合、item(0)null を返すため、null チェックが必要です。nodeValue プロパティは、要素内のテキストコンテンツを連結して取得します。HTML構造によっては、意図しない空白が含まれる場合があることに注意してください。

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