PHP

PHP like a Boss: The Magic of Metaprogramming & Reflection – Part 1


PHP is a Shitty language.

PHP is garbage.

PHP is f**ked up!

I have been constantly molested verbally by developers of other languages like Python and Ruby that think PHP is just outrightly stupid but as a PHP Ninja that I am, I know the good sides, I know the dark sides, I have also explored the ugly sides and overtime I have known how to wield superpowers in PHP that can do what these other languages can & also better.

Metaprogramming is the ability of a program/code to be able to create another piece of code dynamically at runtime and also manipulate itself if need be. Ikem has given a good explanation about it in his post: Ruby on Steroids: The Magic of MetaProgramming – An Unexpected Journey so you can actually just check that out. So much ado about Metaprogramming but PHP can handle this technique pretty well too.

According to Serge Smerting, Metaprogramming :

  • is how programs are self-aware
  • is the art of operating metadata
  • is black magic processed at build step
  • is making the code shorter

Let’s get started with some of the techniques:

1. eval

There is a powerful PHP function that can evaluate a piece of PHP code represented in string format which means that it is possible for one to accept user input or read code off of a file and get it evaluated from within your program.

Let’s change getName to getSomething, now that’s a function that doesn’t exist so it should throw an error:

A typical real world example is WordPress plugins and online code editors. These editors allow you write PHP code and it processes that code to give you the desired output.

Tip: You can use file_get_contents() to read off source code from a file and pass it onto the eval() function to process.

This eval() function is very dangerous because it allows running of any form of PHP code, so be very careful and properly validate any user input that is passed onto this function.

2. __set and __get magic methods

These methods enable you to dynamically create and retrieve properties in a class that never existed during runtime. __get is used to read the value of an undefined property of a class while __set is used to set the value of a new propery of a class at runtime. Let’s get to the code for better understanding.

The name and email properties don’t exist in the class, We created them on the fly, yet we were able to assign values to them and also retrieve those values. How sweet! :smile:

In a Real World, A very good use case for this are ORMs, In a typical ORM you can do something like:

The underlying code makes use of these magic methods to be able to dynamically set any property for the model and check if the names of those properties correspond to column names in the table,…if they do, it saves successfully, if they don’t it throws an appropriate exception. Same applies for also retrieving data from the database.

3. __invoke

This magic method allows you to call an object as if it were a function or even as a closure. How can something be an object and also a function?. Magic right? A trivial example is:

So the object was invoked as a function. This magic method came with PHP 5.3

A practical use case of this is:

The object was invoked as a callback into attends method of the College class.

4. __toString()

This magic method allows us to change the default behaviour of an object when it is been echoed. It returns a string representation. Example:

Here we are echoing the object directly as a string. It’s a very nice shortcut that can shorten the amount of lines of code in your project.

5. __call and __callStatic

With these methods, you can handle situations when methods that don’t exist/publicly accessible are called on an object. Example:

Calling a missisipi method that doesn’t exist in that class throws a FATAL error

Now, let’s take care of methods that don’t exist. Example:

Here, in the __call method, we are explicitly checking with method_exists if the method that is called on the object exists, if it does, go ahead and call the method.

If it was a destroy() method that was called, it should print out You can't call this method on this Class. Too dangerous my friend.

If the method doesn’t exist in that class at all, then report with a custom message that there is no method like that.

__callStatic is used for static functions like so:

6. call_user_func and call_user_func_array

Sometimes you are not sure what methods would be called, in your case, a method call might be determined by a user’s input..how do you handle that dynamically?

So call_user_func calls functions whose name you don’t know ahead of time.

Here we passed callbacks ( anonymous functions), one for addition and another for multiplication and it performed those operations and gave us results because call_user_func was able to call those functions.

call_user_func_array() is very helpful for functions that have complex and variable parameter requirements like so:

 

Conclusion

You have seen some of the magic you can perform on methods and how you can manipulate your programs during runtime. You have also seen how to use code to create code on the fly. We’ll be talking about the Reflection Class and it’s sister classes in the next part of this series.

You’ll receive more POWER as a PHP developer! :smile:

Please let me know if you have any questions or observations in the comments section.

 

PROSPER OTEMUYIWA

About PROSPER OTEMUYIWA

Food Ninja, Code Slinger, Technical Trainer, Accidental Writer, Open Source Advocate and Developer Evangelist.