PHP对象可以响应未定义的方法吗?

Nat*_*ong 0 php ruby-on-rails

Rails依赖于Ruby的一些简洁方面.其中之一是能够响应未定义的方法.

考虑DogOwner.所有者has_many :dogs和狗之间的关系belongs_to :owner.

如果你进入script/console,得到一个狗对象fido = Dog.find(1),并查看该对象,你将看不到被调用的方法或属性Owner.

看到的是一个owner_id.如果你要求fido.owner,对象会做这样的事情(至少,这就是它在我看来):

  1. 我被问到了我的.owner属性.我没有其中一个!
  2. 在我抛出之前NoMethodError,我是否有关于如何处理此问题的规则?
  3. 是的,我这样做:我应该检查一下,看看我是否有owner_id.
  4. 我做!好的,然后我将进行连接并返回该所有者对象.

PHP的文档是 - 嗯 - 有时候有点缺乏,所以我想知道这里是否有人知道答案:

我可以在PHP中为对象定义类似的行为吗?

如果没有,您是否知道这些灵活模型连接的解决方法?

cle*_*tus 8

您可以__call()在PHP中实现该方法,这是一个全部用于调用其他方法无法访问的方法.

class MyObj {
  public function __call($name, $args) {
    $list = $args ? '"' . implode('", "', $args) . '"' : '';
    echo "Call $name($list)\n";
  }
}

$m = new MyObj;
$m->method1(1, 2, 3);
$m->method2();
Run Code Online (Sandbox Code Playgroud)

某些语言(例如Javascript)也具有所谓的第一类函数.这实际上允许您动态添加或删除对象(或类)中的方法.PHP语法(从5.3开始)有点支持这个但它并不真正可用.

$obj = new stdClass;
$obj->foo = function() {
  echo "hello\n";
};

print_r($obj);
Run Code Online (Sandbox Code Playgroud)

输出:

stdClass Object
(
    [foo] => Closure Object
        (
        )

)
Run Code Online (Sandbox Code Playgroud)

但试试:

$obj->foo();
Run Code Online (Sandbox Code Playgroud)

你得到:

Fatal error:  Call to undefined method stdClass::foo() in C:\xampp\htdocs\test.php on line 8
Run Code Online (Sandbox Code Playgroud)

然而:

$f = $obj->foo;
$f();
Run Code Online (Sandbox Code Playgroud)

正确输出hello.