In this tutorial I will show how to really take advantage of PHPs magic methods in the creation of a class that helps us output HTML using only PHP. Outputting large chunks of HTML from PHP can sometimes be a struggle, especially if you have a lot of conditional statements and/or loops.
Imagine you are creating a listing of all your websites users and outputting them into a table. This would require opening a table tag, setting the headers, looping through all the users and output the user data like email and name in different cells and so on and so forth. Some people like to write as much HTML as possible to solve this and open the php tag where needed, and some people like to write it all in PHP and echo the html where needed.
What’s a magic method?
Both of the mentioned solutions are perfectly acceptable and common, it all comes down to preference. My personal preference is to output HTML using PHP in my scripts and only open the PHP tag once. To make it all easier I created a dynamic jquery-like class with the help of PHPs magic methods, so what are these magic methods? Let’s take a look.
Simply put, all methods that start with the double underscore (__methodName) are magic methods. I bet you have already used one; __construct(). The __construct() method is called whenever a new instance of a class is created and this is our first step.
Creating the class
This is our HTMLElement class which we will use to create and output different HTML elements from PHP. As mentioned earlier the __construct method is called when we create a new instance of the class.
The $div object is now an instance of the class HTMLElement with the $tag property set to “div”. Now we just need a clever way to output the HTML. We could create a method called getHtml() or something similar, but PHP already have a magic method we can take advantage of; the __toString() method.
__toString() is called whenever the object, or instance, of our class is treated like a string, like if we do “print $div” or concatenate it to another string. Let’s add the __toString() method to our class.
Now if we use print, or echo, to output $div it will show up as the following in our HTML source.
That’s neat, but what is a HTML tag without the ability to hold attributes or be the parent of child elements? I optimistically guess you noticed the 4 properties we created in the construct method of our class; tag, inner, children and attributes. Let’s go through them one at a time and add the functionality to our __toString() method.
The inner property is a simple string that’s outputted inside the tags of our element, like if we have a paragraph tag with some text.
This is pretty self-explanatory so let’s move on to attributes. We want the element to have several attributes as key/value pairs so this is a perfect opportunity to use an associative array. Let’s first add a couple of attributes to our $div object as well as some inner text.
Now we have two attributes in the associative array, id and class. Now in the __toString() method we need to loop through the attributes array and add all the key/value pairs to the open tag.
Printing our $div object now results in the following HTML:
We are really getting somewhere now. Our last property is the children array, which holds all the child HTML elements of our $div. Notice that the children array can hold both strings and other instances of the HTMLElement class, as it can be treated as a string. Let’s create and add a paragraph element with some inner text as a child of our div.
I added it twice to show the concept of the array. Now once again let’s update the __toString() method.
Wow, that was easy. Remember I said that the __toString() method is called everytime the object is treated like a string? That’s what makes it so easy to add all the child elements, simply loop through them and concatenate them to the $html variable. The $element variable will then, as the loop progresses through the children, return each individual childs HTML.
Print the $div and you will, hopefully, get this output:
Making it all dynamic
So far so good, however, if you think about the problem earlier with the user-table listing. We would need a whole lot of objects. First a table object to hold a thead and tbody object. Then create tr objects that hold td objects and so on. So is this class really the solution to the problem? or just another problem itself? There are still two amazing magic methods that will really simplify and upgrade our class; __call() and __callStatic.
__call() is called whenever we try to call (that’s a lot of ‘calls’) a method on an instance of a class that isn’t defined.
Likewise __callStatic() is called when we try to statically call a function on a class itself, meaning we don’t need an instance. I won’t go into the details here so if that was unclear please read about it here: PHP: Static Keyword
Also notice that the __callStatic() magic method was added in PHP 5.3.0
We are now going to create another class that we will call upon to create our HTML elements a more efficient way.
As mentioned earlier, if we statically run a function on UI that isn’t defined, the __callStatic() will be called with the $function as the name of the function we try to call and $vars as the parameters we pass. We then simply create and return an instance of the HTMLEelement class with the function name as the tag, this make it possible to write code such as this:
That makes nesting the items a lot easier, but to set properties like children, innertext and so on we still need to save the instance as an object and update properties before nesting them, but I have a quick fix for that.
Let’s update the HTMLElement class one last time adding the __call() function.
When we make a call on our HTMLElement instance to a method that isn’t defined, the magic method __call() will run with $name as the name of the method we tried to run and $arguments as an array of arguments we passed.
First we change the $name to be lowercase as this is the name of the HTML attribute that will be added later. Then we check if the name of the function we ran is in the reserved keywords array, if it is we set the instance’ property to the argument we passed. If the name is not reserved we know we are setting and attribute, so basically just add it to the attribute array with value of the argument passed, and return self.
That might have been unclear, not sure I understood it myself, let’s just look at some examples.
So when we call inner, tag or children as a method on the instance the representative property on the object will be set, all other calls that aren’t defined will be set in the attribute array. This makes it possible to set any sort of attribute on our element using calls, isn’t that neat? And since we return $this we can nest them as we want.
You can now see that creating large chunks of HTML is a lot easier. I personally also think this is easier to write as well as easier to read/maintain later on. I bet this could lead to a debate concerning speed, but with todays hardware and high speed internet connections I really don’t think of it as an issue. Object-oriented programming is all about creating modules that make our lives easier – prioritizing efficient writing, readability and ease-of-use.
The user interface project can be found on BitBucket: https://bitbucket.org/stiggro/validator
That’s it, hope you learned something about magic methods and how we can take real advantage of them when used correctly. If you have questions or any kind of feedback please leave a comment.