【问题标题】:Add method in an std object in php在 php 的 std 对象中添加方法
【发布时间】:2012-07-15 05:39:49
【问题描述】:

是否可以通过这种方式添加方法/函数,比如

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

或者像这样

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

如果可能的话,我该如何使用该功能/方法?

【问题讨论】:

    标签: php object stdclass


    【解决方案1】:
    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');
    

    或者您可以创建默认类并使用...

    【讨论】:

      【解决方案2】:

      另一种解决方案是创建一个匿名类并通过魔术函数__call 代理调用,使用箭头函数,您甚至可以保持对上下文变量的引用:

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

      【讨论】:

        【解决方案3】:

        从 PHP 7 开始,也可以直接调用匿名函数属性:

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

        这里的表达式$obj->printMessage 生成匿名函数,然后直接使用参数'Hello World' 执行该函数。但是,在调用函数表达式之前,必须将其放在括号中,这样以下操作仍然会失败:

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

        【讨论】:

          【解决方案4】:

          这现在可以在 PHP 7.1 中通过匿名类实现

          $node = new class {
              public $property;
          
              public function myMethod($arg) { 
                  ...
              }
          };
          
          // and access them,
          $node->property;
          $node->myMethod('arg');
          

          【讨论】:

          • 很好,我在模拟一些数据,这证明很有帮助。
          • 但这是否会向已定义的对象添加新功能?
          【解决方案5】:

          您不能动态地将方法添加到 stdClass 并以正常方式执行它。不过,您可以做一些事情。

          在您的第一个示例中,您正在创建一个closure。您可以通过发出以下命令来执行该闭包:

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

          您可以创建一个 stdClass 对象并为其属性之一分配一个闭包,但由于语法冲突,您不能直接执行它。相反,您必须执行以下操作:

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

          尝试

          $node->method('Argument')
          

          会产生错误,因为 stdClass 上不存在方法“方法”。

          请参阅此SO answer,了解一些使用魔术方法__call 的巧妙黑客。

          【讨论】:

          • +1, 很久以前用其他方式完成的,有人编辑了答案,看日期,但感谢您的努力。
          • 哎呀!我完全忽略了这一点。不过谢谢。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-30
          • 2013-09-23
          • 1970-01-01
          • 2011-04-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多