Help us understand the problem. What is going on with this article?

PHPのDOMを使いやすくする

はじめに

PHPは標準でDOMが使えますが、とても使いにくく、あまり使われていません。
機能が不足していたり、冗長な書き回しになったり、とにかく不便です。

そこで、PHPのDOMを使いやすくするために、自作のプログラムを作りました。
Web標準であるDOMに慣れ親しんだ人なら、簡単に使えるものを目標としています。

技術的には、PHPの DOMDocumentDOMElement拡張したものになっています。

HTMLの入力

最初にベースとなるHTML文字列を渡して document オブジェクトを作成します。

$document = new document('<!DOCTYPE html><html lang="ja"><head><meta charset="utf-8"><title></title></head><body></body></html>');
  • HTMLは、全体を1つのタグで囲っておく必要があります
  • 引数省略時は内蔵テンプレートが使用されます。上記サンプルと同じHTMLです

HTMLの出力

documentオブジェクトは自動的に文字列に変換されるので、出力するだけでHTMLを表示できます。

$document = new document();

print $document; // HTMLを表示する

file_put_contents('example.html', $document); // HTMLをファイルに保存する

$html = "$document"; // 文字列としてコピーする

DOM要素も同様に、自動的に文字列に変換されます

print $document->body; // <body></body> が表示される

id付タグの短縮形

idが付いているタグには$document->id名でアクセスできます。
操作したいタグにはあらかじめidを付けておくと、綺麗なコードが書けます。

$document->exapmle  // $document->getElementById('example') の短縮形

この値はDOM要素です。存在しなければnull

主要タグの短縮形

<html> <head> <title> <body>の主要タグには短縮形があり、$document->タグ名でアクセスできます。

$document->body  // $document->getElementsByTagName('body')[0] の短縮形

$document->title->textContent = 'タイトル名'; //titleはweb標準と異なるので注意

この値はDOM要素です。

属性アクセスの短縮形

属性へのアクセスは短縮形があり、$el->属性名と書けます。

$body = $document->body;

$body->id            // $body->getAttribute('id') の短縮形
$body->id = 'value'  // $body->setAttribute('id', 'value') の短縮形
unset($body->id)     // $body->removeAttribute('id') の短縮形
isset($body->id)     // $body->hasAttribute('id') の短縮形

タグの検索

セレクタで検索

documentオブジェクトには、JavaScriptでお馴染みのquerySelectorがあります。
CSSセレクタを使用して、ドキュメント全体からタグを検索できます。

//単数検索
$document->querySelector('CSSセレクタ')    //戻り値はDOM要素またはnull

//複数検索
$document->querySelectorAll('CSSセレクタ') //戻り値は常に配列

対応セレクタ

検索対象 セレクタ
タグ名 a
id #a
class .a
属性名 [a]
属性名と値 [a="b"]
and ab
子孫 a b
a > b
a + b
弟全て a ~ b
全て *

querySelector()の短縮形

querySelector()には短縮形が用意されていて、jQuery風に書けます。$document('セレクタ')

$document('.example')   // $document->querySelector('.example') の短縮形

デフォルト動作は単数検索です。複数検索するには、セレクタの頭に*を付けます。

$document('*.example')  // $document->querySelectorAll('.example') の短縮形

タグの作成

タグを1つ作成する短縮形

タグの作成には短縮形があり$document(<タグ名>, 本文, [属性名=>属性値])で1つタグが作成できます。
戻り値はDOM要素で、本文と属性は省略できます。

// <div class="example">sample</div> を作る
$document('<div>', 'sample', ['class'=>'example']); 

// 次のコードの短縮形
// $div = $document->createElement('div');
// $div->textContent = 'sample';
// $div->setAttribute('class', 'example');

子タグも一括作成

<ul> <ol> <select> <table> のタグは、本文を配列で渡すと、子タグも一括して作成できます。

ulタグ
$document('<ul>', [1,2], ['id'=>'example']);
//<ul id="example">
//  <li>1</li>
//  <li>2</li>
//</ul>
selectタグ
$document('<select>', [1,2]);
//<select>
//  <option value="1">1</option>
//  <option value="2">2</option>
//</select>
tableタグ
$document('<table>', [1,2]);
//<table>
//  <tr><td>1</td></tr>
//  <tr><td>2</td></tr>
//</table>

$document('<table>', [[1,2], [3,4]]);
//<table>
//  <tr><td>1</td><td>2</td></tr>
//  <tr><td>3</td><td>4</td></tr>
//</table>

HTML文字列をDOM化

HTML文字列を一括してDOM化するには$document('HTML文字列')で可能です。
コンポーネントの読み込みに適しています。

$component = $document('<nav><a id="nav_link">Home</a></nav>'); // コンポーネントの読み込み

$component->nav_link->href = 'http://example.jp/'; // id短縮形が使える。querySelectorもある 

$document->body->appendChild($component); // <body>の最後に<nav>を挿入する

他の方法として$el->innerHTMLでHTML文字列を代入することもできます。

[付録] DOM操作の早見表

DOMでできる代表的な操作をまとめてみました。
DOMに不慣れな人でも次の早見表を使えば大丈夫👍

//タグを検索する
$document->querySelector('セレクタ');    // 戻り値はDOM要素またはnull
$document->querySelectorAll('セレクタ'); // 戻り値は配列

//タグを作成する
$el = $document->createElement('タグ名');// 戻り値はDOM要素


//中身を取得する
$el->textContent; //戻り値はタグを含まない文字列

//中身を取得する
$el->innerHTML;   //戻り値はタグを含む文字列


//中身を変更する
$el->textContent = '文字列はエスケープされる';

//中身を変更する
$el->innerHTML   = '文字列はエスケープされない';

//中身を全て削除する
$el->textContent = '';


//タグ名を取得する
$el->tagName; //戻り値は小文字

//属性を取得する
$el->getAttribute('属性名'); //戻り値は文字列

//属性を設定する
$el->setAttribute('属性名', '属性値');

//属性を削除する
$el->removeAttribute('属性名');


//タグを子の最後に追加する
$el->appendChild($new_el);

//タグを子の最初に追加する
$el->insertBefore($new_el, $el->firstChild);

//タグを前に追加する
$el->parentNode->insertBefore($new_el, $el);

//タグを後ろに追加する
$el->parentNode->insertBefore($new_el, $el->nextSibling);


//タグを置換する
$el->parentNode->replaceChild($new_el, $el);

//タグを削除する
$el->parentNode->removeChild($el);

//タグをコピーする
$el->cloneNode(true); //戻り値はDOM要素


//タグの子孫からタグを検索する
$el->querySelector('セレクタ');    //戻り値はDOM要素またはnull
$el->querySelectorAll('セレクタ'); //戻り値は配列

※PHP8から最新のDOMが使えるようになり、タグの追加・置換・削除が簡単になります。参考

ソースコード

ダウンロード

ファイルをincludeするだけで使えます。ご自由にお使いください。

economist
経済学者です。統一経済理論の作者
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away