Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 给孩子打电话&x27__如果方法存在,则调用该方法,如果不存在,则引发异常_Php_Oop_Magic Methods - Fatal编程技术网

Php 给孩子打电话&x27__如果方法存在,则调用该方法,如果不存在,则引发异常

Php 给孩子打电话&x27__如果方法存在,则调用该方法,如果不存在,则引发异常,php,oop,magic-methods,Php,Oop,Magic Methods,[编辑]更新标题以更准确地反映问题 我试图解决的问题是:我需要知道是否通过parent::调用了一个方法,虽然我可以使用debug\u backtrace,但似乎必须有更好的方法来实现这一点 我一直在研究后期的静态绑定,但可能我对它的理解还不够透彻,无法找到解决方案 所讨论的方法是\uu call,因此我不能简单地传入一个额外的参数,因为多个或少个参数都是错误的 试图解决此问题的原因是父类有\u调用,但子类可能有也可能没有\u调用。如果孩子没有,而家长没有分派调用,那么我想抛出一个异常或错误。如

[编辑]更新标题以更准确地反映问题

我试图解决的问题是:我需要知道是否通过
parent::
调用了一个方法,虽然我可以使用
debug\u backtrace
,但似乎必须有更好的方法来实现这一点

我一直在研究后期的静态绑定,但可能我对它的理解还不够透彻,无法找到解决方案

所讨论的方法是
\uu call
,因此我不能简单地传入一个额外的参数,因为多个或少个参数都是错误的

试图解决此问题的原因是父类有
\u调用
,但子类可能有也可能没有
\u调用
。如果孩子没有,而家长没有分派调用,那么我想抛出一个异常或错误。如果孩子确实有这个方法,那么我将返回
false
(不,我们没有处理这个问题),并让孩子
\u调用
方法继续

到目前为止,我唯一有效的解决方案是将子调用
父::u调用
包装在try/catch块中,如果父调用未路由请求,则默认情况下会引发异常


如果父级不处理该方法,则抛出异常,我只是想看看是否有更优雅的解决方案,因为将异常用于流控制似乎不太正确。但是使用stacktrace也不能找出调用者。

这应该在父类中完成:

if (__CLASS__ != get_class($this))

我不完全确定这是否符合你的需要,我也认为这种黑客行为从OO设计的角度来看是非常糟糕的。然而,编写代码是一件有趣的事情:)

将产生:

Parent
Child handle!
PHP Fatal error:  Uncaught exception 'Exception' with message 'No method' in /home/andres/workspace/Playground/test.php:18
Stack trace:
#0 /home/andres/workspace/Playground/test.php(58): ParentClass->__call('foo', Array)
#1 /home/andres/workspace/Playground/test.php(58): ChildClass2->foo()
#2 {main}

HTH

在使用后期状态绑定时,您不了解的是什么?这会告诉我子类的名称和父类的名称,但实际上不会让我确定是否存在子类调用方法这会得到您想要的,但是我建议OP把你的子类知识放到父类中是一种糟糕的设计方法。@Will,它回答了标题中的问题。您的子类将始终有一个
\u调用
方法,因为它从父类继承它。您必须进行大量的自省,以确定您的子类是否有自己的
\u调用
方法。这听起来像是糟糕的应用程序结构。父母根本不应该意识到自己的孩子。子类会在适当的情况下重写父类,而不会重写任何其他内容。@如果调用来自非自身的类,那么它一定来自子类(这是除非在子类调用
parent::\u call()
中有其他方法,这将是一种更疯狂的设计方法)。我想补充一点,我个人认为更好的编码实践是
\u call()
仅用于引发异常(即对类的无效方法调用),并具体实现您想要使用的方法。这使代码中的意图更加清晰,并使如何覆盖子类中的特定方法更加清晰。如果您实际上在
\u call()
方法中为许多方法调用实现扩展逻辑,并且您对该方法进行了更改,则可能会中断对该类的所有方法调用,而不仅仅是您更改的方法调用。
<?php

class ParentClass 
  {
  public function __call( $method, $params ) 
  {
    if($method === 'one')
    {
      echo "Parent\n";
      return true;
    }
    elseif($this->shouldForwardToSubclass($method)) 
      {
        return false;
      }
    else 
    {
      throw new Exception("No method");
    }
  }

   protected function shouldForwardToSubclass($methodName)
   {
      $myClass = get_class($this);
      if (__CLASS__ != $myClass)
      {
        $classObject = new ReflectionClass($myClass);
        $methodObject = $classObject->getMethod('__call');
        $declaringClassName = $methodObject->getDeclaringClass()->getName();
        return $myClass == $declaringClassName;
      }
      else 
          {
            return false;
          }
}

}

class ChildClass1 extends ParentClass {
  public function __call( $method, $params ) {
    if( ! parent::__call( $method, $params ) ) 
    {
      echo "Child handle!\n";
    }
  }
}

class ChildClass2 extends ParentClass {
}
$c = new ChildClass1();
$c->one();
$c->foo();

$c = new ChildClass2();
$c->foo();
Parent
Child handle!
PHP Fatal error:  Uncaught exception 'Exception' with message 'No method' in /home/andres/workspace/Playground/test.php:18
Stack trace:
#0 /home/andres/workspace/Playground/test.php(58): ParentClass->__call('foo', Array)
#1 /home/andres/workspace/Playground/test.php(58): ChildClass2->foo()
#2 {main}