Add method in an std object in php

后端 未结 4 1425
说谎
说谎 2021-01-01 14:13

Is it possible to add a method/function in this way, like

$arr = array(
    \"nid\"=> 20,
    \"title\" => \"Something\",
    \"value\" => \"Somethi         


        
相关标签:
4条回答
  • 2021-01-01 14:47

    You cannot dynamically add a method to the stdClass and execute it in the normal fashion. However, there are a few things you can do.

    In your first example, you're creating a closure. You can execute that closure by issuing the command:

    $arr['my_method']('Argument')
    

    You can create a stdClass object and assign a closure to one of its properties, but due to a syntax conflict, you cannot directly execute it. Instead, you would have to do something like:

    $node = new stdClass();
    $node->method = function($arg) { ... }
    $func = $node->method;
    $func('Argument');
    

    Attempting

    $node->method('Argument')
    

    would generate an error, because no method "method" exists on a stdClass.

    See this SO answer for some slick hackery using the magic method __call.

    0 讨论(0)
  • 2021-01-01 14:48

    Since PHP 7 it is also possible to directly invoke an anonymous function property:

    $obj = new stdClass;
    $obj->printMessage = function($message) { echo $message . "\n"; };
    echo ($obj->printMessage)('Hello World'); // Hello World
    

    Here the expression $obj->printMessage results in the anonymous function which is then directly executed with the argument 'Hello World'. It is however necessary to put the function expression in paranetheses before invoking it so the following will still fail:

    echo $obj->printMessage('Hello World'); 
    // Fatal error: Uncaught Error: Call to undefined method stdClass::printMessage()
    
    0 讨论(0)
  • 2021-01-01 14:53

    This is now possible to achieve in PHP 7.1 with anonymous classes

    $node = new class {
        public $property;
    
        public function myMethod($arg) { 
            ...
        }
    };
    
    // and access them,
    $node->property;
    $node->myMethod('arg');
    
    0 讨论(0)
  • 2021-01-01 14:56

    Another solution would be to create an anonymous class and proxy the call via the magic function __call, with arrow functions you can even keep reference to context variables:

     new Class ((new ReflectionClass("MyClass"))->getProperty("myProperty")) {
                public function __construct(ReflectionProperty $ref)
                {
                    $this->setAccessible = fn($o) => $ref->setAccessible($o);
                    $this->isInitialized = fn($o) => $ref->isInitialized($o);
                    $this->getValue = fn($o) => $ref->getValue($o);
                }
    
                public function __call($name, $arguments)
                {
                    $fn = $this->$name;
                    return $fn(...$arguments);
                }
    
        }
    
    0 讨论(0)
提交回复
热议问题