phpsyntaxstatic-methodsmethod-call

What kind of PHP syntax is this?


Can you please tell me what kind of PHP syntax is:

echo Html::{'div.my-class#my-id'}('This is element content')

?

It's from https://github.com/decodelabs/tagged library.

I mean I know what it does, but I don't understand the syntax used and why it works :) (braces immediately after the scope operator). Looks like they're using braces to 'generate' the name of the function to call, but - on the other hand - it contains characters like '.' and '#" and variable parameters ('my-class', 'my-id'). I'm confused...

I tried googling for over 2 hours, but no luck :/


Solution

  • let's reconstruct this from first principle

    1. you can use {value} to put a dynamic method/attribute name

    i.e if you have

    class Dog {
        public string $name = 'doggy';
        public function walk() {
        }
    }
    

    you can do

    $dog = new Dog();
    $dog->walk(); 
    $dog->{'walk'}(); // equivalent 
    
    echo $dog->name;
    echo $dog->{'name'};
    

    as you can do this and 'walk' and name are value, they can also come from variables

    $attribute = 'name';
    $dog->{$attribute};
    
    1. PHP has some magic methods to treat undefined method / attributes , the full list is there https://www.php.net/manual/en/language.oop5.overloading.php

    for example __callStatic() will be called whenever you call a static method for which the name is undefined

    like this

    class Html
    {
        static public function __callStatic($name, $arguments)
        {
            // Note: value of $name is case sensitive.
            echo "Calling object method '$name' "
                 . implode(', ', $arguments). "\n";
        }
        
    };
    
    Html::iDontExist();
    

    will output Calling object method 'iDontExist'

    1. now if we mix both 1 and 2 we can do
    Html::{"Hello world"};
    

    It will output Calling object method 'Hello World'

    Conclusion

    1. using {} syntax you can have method that don't follow normal convention (i.e they can have spaces, emoji, special caracters etc. )
    2. using overloading magic method like __callStatic you can have methods that don't exists before hand

    so by combining 1 and 2 your library is allowing a method to already be an argument by itself and all the logic of treating this name will be in a __callSatic

    so it would be the same as doing Html::something('div.my-class#my-id', 'This is element content' ) if something was a defined static method