Agregar método en un objeto estándar en php

3 minutos de lectura

El avatar de usuario de Alpha
el alfa

¿Es posible agregar un método/función de esta manera, como

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

o tal vez así

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

y si es posible, ¿cómo puedo usar esa función/método?

Esto ahora es posible de lograr en PHP 7.1 con clases anónimas

$node = new class {
    public $property;

    public function myMethod($arg) { 
        ...
    }
};

// and access them,
$node->property;
$node->myMethod('arg');

  • Buena, me estaba burlando de algunos datos y esto resultó bastante útil.

    – Nick M.

    28 de septiembre de 2017 a las 0:08

  • pero ¿agrega esto una nueva función a un objeto ya definido?

    – Geomorillo

    11 de octubre de 2018 a las 2:53

  • @Geomorillo, No, no se agrega al objeto, puede “agregar función a la clase” con extends en (anónimo) clase. Es php, no es JavaScript. Pero en otras respuestas también puede ver soluciones ilegibles con __call.

    – usuario1742529

    23 de febrero a las 2:23

avatar de usuario de keelerm
keelerm

No puede agregar dinámicamente un método a stdClass y ejecutarlo de la manera normal. Sin embargo, hay algunas cosas que puedes hacer.

En su primer ejemplo, está creando un cierre. Puede ejecutar ese cierre emitiendo el comando:

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

Puede crear un objeto stdClass y asignar un cierre a una de sus propiedades, pero debido a un conflicto de sintaxis, no puede ejecutarlo directamente. En su lugar, tendrías que hacer algo como:

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

Tratando

$node->method('Argument')

generaría un error, porque no existe ningún método “método” en una stdClass.

Vea esta respuesta SO para algunos hackers hábiles usando el método mágico __llamada.

  • +1, se hizo de otras maneras hace mucho tiempo, alguien editó la respuesta, vea la fecha, pero gracias por su esfuerzo.

    – El alfa

    9 de julio de 2013 a las 2:12


  • ¡Vaya! Pasé por alto eso por completo. Gracias de cualquier forma.

    – keelerm

    9 de julio de 2013 a las 2:16

Desde PHP 7 también es posible invocar directamente una propiedad de función anónima:

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

Aquí la expresión $obj->printMessage da como resultado la función anónima que luego se ejecuta directamente con el argumento 'Hello World'. Sin embargo, es necesario poner la expresión de la función entre paréntesis antes de invocarla para que lo siguiente siga fallando:

echo $obj->printMessage('Hello World'); 
// Fatal error: Uncaught Error: Call to undefined method stdClass::printMessage()

avatar de usuario de g13013
g13013

Otra solución sería crear una clase anónima y representar la llamada a través de la función mágica. __callcon funciones de flecha incluso puede mantener la referencia a las variables de contexto:

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

    }

Avatar de usuario de Abolfazl
Abolfazl

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

O puede crear una clase predeterminada y usar …

¿Ha sido útil esta solución?