30

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

$arr = array(
    "nid"=> 20,
    "title" => "Something",
    "value" => "Something else",
    "my_method" => function($arg){....}
);

or maybe like this

$node = (object) $arr;
$node->my_method=function($arg){...};

and if it's possible then how can I use that function/method?

5 Answers 5

39

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');
Sign up to request clarification or add additional context in comments.

3 Comments

Nice one, I was mocking some data and this proved pretty helpful.
but does this add a new function to an already defined object?
@Geomorillo, No, it does not add to object, you can "add function to class" with extends on (anonymous) class. It is php, it is not JavaScript. But on other answers you can see also unreadable solutions with __call.
20

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.

Comments

14

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()

Comments

0

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);
            }

    }

Comments

0
class myclass {
function __call($method, $args) {
if (isset($this->$method)) {
$func = $this->$method;
return call_user_func_array($func, $args);
}
}
}
$obj = new myclass();
 $obj->method = function($var) { echo $var; };

$obj->method('a');

Or you can create defult class and use...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.