Skip to content
g105b edited this page Mar 21, 2013 · 8 revisions

PHP.Gt comes with a powerful DOM manipulation engine to allow you to modify the HTML from your PageViews before returning it to the browser. The DOM is made available to all PageCode and PageTool objects as the second parameter to their go(...) function.

The $dom object can queried using either CSS or XPath selectors. These queries will always return a DomElCollection object representing the list of matching DomEl objects. Properties and methods on the DomEl object (such as appendChild(), insertBefore(), textContent and classList) are mapped through to the containing DomElCollection. You can also query from a DomElCollection (and the selection will be applied to all DomEls in it), using the same syntax.

Accessing the DOM via CSS selectors

  • Syntax: $matchingElements = $dom->css("css selector string");
  • Shorthand: $matchingElements = $dom["css selector string"]; // Note the use of square brackets.

The current state of the CSS selection mechanism is up to (CSS level 2.1)[http://www.w3.org/TR/CSS21/]

Accessing the DOM via XPath

  • Syntax: $matchingElements = $dom->xpath("xpathSelectorString");

All valid XPath expressions are supported (they are passed-through to the PHP DomXPath method).

Querying using xpath has a benefit over CSS selection when applied to a DomElCollection or DomEl fragment, in that you can access parent nodes (or even the DOM root), rather than being restricted to accessing children of the current node. For example,

$domFragment->xpath("..");

would return the $domFragments parent element rather than only looking inside the $domFragment. The query is run in the context of the $domFragment though, so:

$domFragment->xpath("//a");

will return all a children of the fragment, rather than all as in the whole DOM.

Manipulating the DOM

As the DOM manipulation in PHP.Gt simply extends the existing functionality of PHP's built-in DOM, DOM manipulation is achieved using familiar techniques.

List-building example

In the following example, all variables will be read from the querystring and placed into an unordered list. The result of visiting http://example.com/Test.html?Name=Dave&FavouriteDrink=Cola will be a bulleted list that looks like this:

  • Name: Dave
  • FavouriteDrink: Cola

Test.html

<!doctype html>
<h1>List of variables in the querystring</h1>
<ul id="qsList">
</ul>

<p id="noVars">
    There are no variables in the querystring. <a href="?TestKey=TestValue">Click here to add one</a>.
</p>

Test.php

<?php class Test_PageCode extends PageCode {

public function go($api, $dom, $template, $tool) {
    if(!empty($_GET)) {
        // The querystring is *not* empty - remove the empty message.
        $dom["p#noVars"]->remove();
    }

    // Obtain a reference to the UL element, using its CSS selector.
    $ulElement = $dom["ul#qsList"];

    foreach($_GET as $key => $value) {
        // Create a new LI for every key in the querystring.
        $liElement = $dom->createElement("li");
        // Set the text content to our required format.
        $liElement->textContent = "$key: $value";

        // Add the LI to the end of the UL using W3C standard functions.
        $ulElement->appendChild($liElement);
    }
}

}?>

As a rule of thumb, HTML elements should never be created or emitted from PHP code (apart from simple examples such as the above). It is best practice for the elements to always be extracted from the DOM and manipulated. To make this easier, PHP.Gt introduces template elements to help build dynamic content such as lists.

The above example uses standards-based DOM manipulation, apart from the remove() method, called on the paragraph element when the querystring is not empty.

The remove() method is a helper method, added by PHP.Gt. There are various helper methods put in place where the standard DOM techniques are a little long-winded. For example, to remove an element from the DOM using standard techniques, the following code is required:

// Standard DOM technique for removing an element:
$domElement->parentElement->removeChild($domElement);

// PHP.Gt helper method for achieving the same result:
$domElement->remove();

The following example shows how a few other helper methods added by PHP.Gt can be used in real-world scenarios.

Outputting elements from a data source

We won't go into database connections or details of how to connect to other data sources in this chapter, but it is very common for PHP applications to have to output to the page according to some data that is provided to PHP from an external source.

Let's assume that we already have access to this data within an array, and it is a list of products within product categories. In this example, the list of categories will be output into a <select> element, and changing the category will display a list of products within that category.

Products.html

<!doctype html>
<h1>Products list</h1>

<p>Pick a category from the list below to see our products.</p>

<form>
    <select id="categoryList" name="Category">
        <option>Choose a category</option>
    </select>

    <button>Change category</button>
</form>

<ul id="productList">
</ul>

The above page is very simple. There is a <form> element with no action or method attributes, so will have the default behaviour of performing a GET request to the current page.

Within the form is a <select> element with the name of "Category". This name will be submitted in the GET request, along with the value of the selected <option> element. However, there are no option elements in the select with a value... that's where PHP comes in.

Products.php

<?php class Products_PageCode extends PageCode {

// Let's hard-code the data here - assume it has been provided by a data-source.
private $_productCategoryData = [
    ["ID" => 1, "Name" => "Computers", "Products" => ["Macbook", "Thinkpad", "Surface"]],
    ["ID" => 2, "Name" => "Phones",    "Products" => ["iPhone", "Blackberry", "Galaxy", "Lumina"]],
    ["ID" => 3, "Name" => "Other",     "Products" => ["HDTV", "Washing Machine", "Video Camera"]],
];

public function go($api, $dom, $template, $tool) {
    // Use the helper method "appendArray" to append the data from within ProductCategoryData
    // as "option" elements with "value" attributes according to the data's "ID" key,
    // and a text value according to the data's "Name" key.
    $dom["select#categoryList"]->appendArray(
        $this->_productCategoryData,
        "option",
        ["value" => "ID"],
        "Name"
    );

    // Don't continue any further if there isn't a category selected.
    if(!isset($_GET["Category"])) {
        return;
    }

    // Obtain a reference to the UL element.
    $ul_productList = $dom["ul#productList"];

    // Loop over the currently selected category's elements.
    foreach($this->_productCategoryData[$_GET["Category"]]["Products"] as $product) {
        $li_product = $dom->createElement("li");
        $li_product->textContent = $product;

        $ul_productList->appendChild($li_product);
    }

    // Just for fun, let's randomise the order of the list.
    $ul_productList->shuffle();
}

}?>

For a more detailed breakdown of PHP.Gt's DOM capabilities, check out the Advanced DOM usage page.

Next page - Accessing the API system Back to documentation

Clone this wiki locally