In PHP you can use square brackets on an element to access attributes:
$node = /* SimpleXMLElement */
$id = $node['id'];
What's weird is that $id
isn't a string, It's another SimpleXMLElement
. Why isn't it a string? I find myself using strval()
all over the place on this.
How are the square brackets working? Can I do that with my own classes? I Haven't seen anything in the docs about this.
I believe you can extend the SimpleXML class, and implement the ArrayAccess in that.
As for SimpleXML itself, it is an internal class. The only interface it implements for PHP userspace is
Traversable
.Internally when accessed with square brackets, SimpleXML looks for things depending on the value and type of the index/key.
If the type is integer (long), tries to find the zero-indexed, numbered element and offer its value. If you have a concrete node element like
$root
for the root element,$root[0]
will represent the value of that element:The root element is a bit uninteresting because there only exists one. It is more interesting with elements that have parents.
Sets the node-value of the first
child
element. An index up-one will add a new child:This pretty much works like with arrays. Strings that are an integer number, work like an integer:
And leaving the brackets empty, will add a new element at the end:
So far for integers and "no" offset. Like with a standard PHP array, this must not be confused with passing
NULL
. It would be converted to an empty string""
.With any string, SimpleXML will look for an attribute node instead of a child element node:
This also works for adding attributes:
An edge-case is using an empty string (
""
) orNULL
because simplexml then errors out saying that an attribute with no name is invalid. Makes sense as attributes must have a name:Another more special case is the support of the
__toString
magic method. If you pass an object as offset, SimpleXML will try to convert it to string via the magic method. It will then use the returned string as described above.To summarize: The
SimpleXMLElement
class does not implement theArrayAccess
interface but as it is an internal class, it can add an array-similar behavior. And SimpleXML does exactly that.The utility function in PHP sources is called
sxe_prop_dim_read
.But what about when you want to do something similar with your classes?
That is what the
ArrayAccess
interface is for. Implement it in your own classes. PHP already takes some of the work for you internally to make offsets more array-like: integer stay integer; string like an integer are converted to integer and booleans are converted to integer.However
ArrayAccess
allows more than a standard array: valid offsets are floats, NULL, arrays and objects.Especially with
NULL
, you are not able to differ between setting the offsetNULL
or setting a new element - both cases will provideNULL
as offset.An example implementation of the interface is available with another question: PHP, SPL, ArrayAccess Interface.
I guess it's the magic method __get()
Edit: I think I guessed wrong. Didn't know of the Array Access interface yet.
You can provide Array like access to your object by implementing the ArrayAccess interface, which is part of the PHP Standard Library. This interface is one of those "even if you don't have the full PHP Standard Library extension installed, you still have this interface available in PHP 5" things.
By implementing this interface, and defining four methods for your class
you should be able to use square brackets with your instantiated objects.
As for SimpleXML itself, I'm not sure if it actually implements the ArrayAccess interface, or if there's something else going on behind the scenes in the PHP source that gives it these super powers.