DEV Community

david duymelinck
david duymelinck

Posted on

PHP fun: anonymus functions

@jszutkowski has written a benchmark post about anonymus functions in class methods. But is was the strange class binding that made me want to dig in some more.

Object binding in a class method

Because I never needed this binding it was moved to the cold storage in my brain. I mostly use anonymus functions in a class method as an argument for the array map, filter and reduce functions.

So I was thinking what would a scenario be where I want to use the binding. And the thing I came up with was a full name of a user as a property hook. Most of the time it is a simple concatination, return $this->firstName . ' ' . $this->lastName;. But what if it had some options.

class User
{
   // boring user class stuff here

   public Closure $fullName {
      get 
      {
          return function(FullNameOption $option) {
            $arr = ['firstName' => $this->firstName, 'lastName' => $this->lastName];

            return match($option) {
              FullNameOption::String => $this->firstName . ' ' . $this->lastName,
              FullnameOption::JsonString => json_decode($arr),
              FullNameOption::Array => array_values($arr),
              FullNameOption::AssociatedArray => $arr,
            };
         };
      }
   }
}
Enter fullscreen mode Exit fullscreen mode

The annoying thing in PHP is that you can't call the closure direct. $user->fullName(FullNameOption::String) causes a fullName method not found error.

IIFE to the rescue

The fullName closure can be called by using $user->fullName->__invoke(FullNameOption::String). But who want to write that.

Most people know the syntax (new User())->setFirstName('test'), or if you have an invokable class, (new HomeController())().
You can do the same with an anonymus function.

echo (function(string $name) {
  return "Hello $name";
})('test');
// bonus: you can also call regular functions
echo (strtoupper(...))('test');
Enter fullscreen mode Exit fullscreen mode

So to get the full name the cleanest way is to use ($user->fullName)(FullNameOption::String).

Conclusion

Most people are not going to need the object binding for the anonymus functions, so always use static when you use them in class methods.
Also IIFE is not something that will be used frequently.

A cleaner way to get the full name is to use a function instead of a property. But it was a bit of a challenge to get the pieces together, so that was fun.

Top comments (0)