The Object System
The highly visible px class actually does very little. The real power comes from the root class, pxObject, and the variety of px_method sub-classes. Nearly all of the documented public "methods" are actually implemented by instances of px_method sub-classes.
All three pxObject subclasses implement the same methods and can be used interchangeably, but px_nodes and px_method objects are created by and depend on the existence of an owning px object.
The pxObject class is by far the largest in the library. It ties it's subclasses together, providing the glue for the "functions-as-objects" implementation that lets this PHP library imitate jQuery's syntax.
Most of the documented methods return an object that inherits from pxObject, and any pxObject subclass can call any of the documented methods available. That's what gives us the power to call the methods in a string or save the results in PHP variables equally.
Functions Return $this
In order for functions to be strung together, each one must return an object that has the power to call the next.
Consider the following code:
$doc = new px("myImages.html"); $img = $doc->xpath("//img")->attr("title","Image");
In the second line, the px $doc (a subclass of pxObject) calls the xpath method, which returns itself (ultimately a pxObject). That return value is then used to call the "attr" method. Because attr returns itself, the final return value - the value that the $img variable is set to - is now a pxObject.
The xpath "function" is actually a method of the px_method_xpath class, a subclass of px_method, a subclass of pxObject. The attr "function" is actually a method of the px_method_attr class (also a subclass of px_method, then pxObject). Only pxObject gives px_method_xpath the power to call px_method_attr.
The ability for each to call the next comes from the fact that these methods both returns $this - a px_method, which is based on pxObject.
Functions Usually Return $this
Functions Store Their State
In order for function results to be stored in variables, each must store it's own state. This is accomplished by the fact that functions are implemented as methods of objects that inherit from of the class px_method.
Each time a function is called, a new instance of a px_method subclass is instantiated, and is passed it's owning px_object and the currently selected nodes. Any method that changes the currently selected nodes must instantiate and store the new selected node list, which will be passed to the next function/method it calls.
Consider the following code:
<div> <b title='Y'>1</b> <b title='Z'>2</b> <b>3</b> </div>
$doc = new px("BoldTitles.xml"); $b2 = $doc->xpath("//b")->attr("title","X")->xpath("//b"); $doc->xpath("//b")->attr("title",$b2->attr("title")); $b2->attr("title","Y");
<div> <b title="X">1</b> <b title="Y">2</b> <b title="Z">3</b> </div>
Notice in line 2 how the first xpath("//b") result, which was used to set the first b tag's title, is overridden by the second xpath("//b") call, and $b2 is set to the second b tag. Then the $b2 variable is accessed after the third xpath("//b") call in line three, setting the third b tag's title to it's own value. The $b2 variable retains it's own node list until the end, when it sets it's own title attribute to "Y".
Some Utility Methods
- px() returns the px (document) object associated with any pxObject.
- nodes() returns the DOMNodeList (or equivalent) object associated with a pxObject.
- get($n) returns the DOMNode object corresponding to the $Nth matched node.
- index($n) returns the $Nth matching PX object.