skip to Main Content

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 :/

3

Answers


  1. The following code does not answer the question, but shows a working example:

    class weird_php_magic
    {
        public static function __callStatic(
            string $method,
            array $args
        ): string|Stringable|null {
            return static::convert($method, ...$args);
        }
        
        public static function convert(
            string $name,
            mixed $content,
            ?array $options = [],
            ?callable $setup = null
        ): string|Stringable|null {
            var_dump($name);
            var_dump($content);
            
            return null;
        }
    }
    
    weird_php_magic::{'this does not exist'}('nor this');
    

    OUTPUT

    string(19) "this does not exist"
    string(8) "nor this"
    

    I tested this code with PHP 8.2. Once the convert() function has the name and text, it should then be fairly straightforward to parse the details and (for example) add an HTML element to the DOM or manipulate an existing element.

    Login or Signup to reply.
  2. 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

    Login or Signup to reply.
  3. I think there’s a class named HTML which is calling a static method dynamically to output some HTML.

    In the example below, I’m dynamically calling a method which, in a simple way, does the same thing. I’m also passing an argument to generate additional text.

    <?php
    
    class myClass {
    
        protected function foo($string) {
            echo 'foo says: ' . $string;
        }
        
        protected function bar($string) {
            echo 'bar says: ' . $string;
        }
    
        public function hello($method, $string)
        {
            return $this->{$method}($string);
        }
    
        // static methods
        protected static function baz($string) {
            echo 'baz says: ' . $string;
        }
        
        public static function staticHello($method, $string)
        {
            return self::{$method}($string);
        }
    
    }
    
    $class = new MyClass;
    
    // dynamically call the `foo` method and pass a string
    $class->hello('foo', 'this is my foo string');
    
    // outputs
    // foo says: this is my foo string.
    
    $class->hello('bar', 'this is my bar string');
    
    // outputs
    // bar says: this is my bar string.
    
    // static
    $class::staticHello('baz', 'this is my baz string');
    
    // outputs
    // baz says: this is my baz string
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search