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}