PHP检查继承的父项是否存在(当前范围而不是$this)
我希望我能把这写清楚 案例: 我有一个基类PHP检查继承的父项是否存在(当前范围而不是$this),php,inheritance,parent,Php,Inheritance,Parent,我希望我能把这写清楚 案例: 我有一个基类Foo Foo可以有一个方法(在示例中)::run 另一个类Bar扩展了Foo,并有自己的方法::runBar(以及编写Bar)的开发人员不知道父Foo是否拥有或将拥有方法::run 这就是为什么Bar无论如何都要在parent上调用当前方法的原因 助手方法::callParentMethodIfExists应执行其工作,并检查$method是否存在于parent上 到目前为止还不错: 调用Bar::run Bar::run调用::callParent
Foo
Foo可以有一个方法(在示例中)::run
另一个类Bar
扩展了Foo
,并有自己的方法::run
Bar
(以及编写Bar
)的开发人员不知道父Foo
是否拥有或将拥有方法::run
这就是为什么Bar
无论如何都要在parent
上调用当前方法的原因
助手方法::callParentMethodIfExists
应执行其工作,并检查$method
是否存在于parent
上
到目前为止还不错:
- 调用
Bar::run
调用Bar::run
::callParentMethodIfExists
调用::callParentMethodIfExists
如果存在parent::run
Baz
扩展了Bar
并且Baz
没有具有::run
方法,那么:
- 调用从
Bar
- 正在执行
Bar::run
调用Bar::run
::callParentMethodIfExists
调用::callParentMethodIfExists
并检查::parentMethodExists
($this
)是否有父方法Baz
::run
Baz
有一个parent::run
(即Bar::run
ofc)但这不是我应该检查它的范围
简言之
助手方法::callParentMethodIfExists
和::parentMethodExists
应该不检查$this
。他们应该在有问题的方法首次出现时检查范围
代码
class Foo
{
public function run()
{
echo __METHOD__ . PHP_EOL;
}
}
class Bar extends \Foo
{
public function run()
{
$this->callParentMethodIfExists(__FUNCTION__);
echo __METHOD__ . PHP_EOL;
}
/**
* Calls the given parent method if exists.
*
* @param string $method
*
* @return null|mixed
*/
protected function callParentMethodIfExists($method)
{
if ($this->parentMethodExists($this, $method)) {
return parent::$method();
}
return null;
}
/**
* @param mixed $class An object (class instance) or a string (class name).
* @param string $method The method name.
*
* @return bool
*/
public function parentMethodExists($class, $method)
{
foreach (class_parents($class) as $parent) {
if (method_exists($parent, $method)) {
return true;
}
}
return false;
}
}
class Baz extends \Bar{}
(new \Baz())->run();
// out:
// Foo::run
// Bar::run
class Foo{}
class Bar extends \Foo
{
public function run()
{
$this->callParentMethodIfExists(__FUNCTION__);
echo __METHOD__ . PHP_EOL;
}
/**
* Calls the given parent method if exists.
*
* @param string $method
*
* @return null|mixed
*/
protected function callParentMethodIfExists($method)
{
if ($this->parentMethodExists($this, $method)) {
return parent::$method();
}
return null;
}
/**
* @param mixed $class An object (class instance) or a string (class name).
* @param string $method The method name.
*
* @return bool
*/
public function parentMethodExists($class, $method)
{
foreach (class_parents($class) as $parent) {
if (method_exists($parent, $method)) {
return true;
}
}
return false;
}
}
class Baz extends \Bar{}
(new \Baz())->run();
// out:
// Fatal error: Uncaught Error: Call to undefined method Foo::run() in
工作案例
class Foo
{
public function run()
{
echo __METHOD__ . PHP_EOL;
}
}
class Bar extends \Foo
{
public function run()
{
$this->callParentMethodIfExists(__FUNCTION__);
echo __METHOD__ . PHP_EOL;
}
/**
* Calls the given parent method if exists.
*
* @param string $method
*
* @return null|mixed
*/
protected function callParentMethodIfExists($method)
{
if ($this->parentMethodExists($this, $method)) {
return parent::$method();
}
return null;
}
/**
* @param mixed $class An object (class instance) or a string (class name).
* @param string $method The method name.
*
* @return bool
*/
public function parentMethodExists($class, $method)
{
foreach (class_parents($class) as $parent) {
if (method_exists($parent, $method)) {
return true;
}
}
return false;
}
}
class Baz extends \Bar{}
(new \Baz())->run();
// out:
// Foo::run
// Bar::run
class Foo{}
class Bar extends \Foo
{
public function run()
{
$this->callParentMethodIfExists(__FUNCTION__);
echo __METHOD__ . PHP_EOL;
}
/**
* Calls the given parent method if exists.
*
* @param string $method
*
* @return null|mixed
*/
protected function callParentMethodIfExists($method)
{
if ($this->parentMethodExists($this, $method)) {
return parent::$method();
}
return null;
}
/**
* @param mixed $class An object (class instance) or a string (class name).
* @param string $method The method name.
*
* @return bool
*/
public function parentMethodExists($class, $method)
{
foreach (class_parents($class) as $parent) {
if (method_exists($parent, $method)) {
return true;
}
}
return false;
}
}
class Baz extends \Bar{}
(new \Baz())->run();
// out:
// Fatal error: Uncaught Error: Call to undefined method Foo::run() in
非工作案例
class Foo
{
public function run()
{
echo __METHOD__ . PHP_EOL;
}
}
class Bar extends \Foo
{
public function run()
{
$this->callParentMethodIfExists(__FUNCTION__);
echo __METHOD__ . PHP_EOL;
}
/**
* Calls the given parent method if exists.
*
* @param string $method
*
* @return null|mixed
*/
protected function callParentMethodIfExists($method)
{
if ($this->parentMethodExists($this, $method)) {
return parent::$method();
}
return null;
}
/**
* @param mixed $class An object (class instance) or a string (class name).
* @param string $method The method name.
*
* @return bool
*/
public function parentMethodExists($class, $method)
{
foreach (class_parents($class) as $parent) {
if (method_exists($parent, $method)) {
return true;
}
}
return false;
}
}
class Baz extends \Bar{}
(new \Baz())->run();
// out:
// Foo::run
// Bar::run
class Foo{}
class Bar extends \Foo
{
public function run()
{
$this->callParentMethodIfExists(__FUNCTION__);
echo __METHOD__ . PHP_EOL;
}
/**
* Calls the given parent method if exists.
*
* @param string $method
*
* @return null|mixed
*/
protected function callParentMethodIfExists($method)
{
if ($this->parentMethodExists($this, $method)) {
return parent::$method();
}
return null;
}
/**
* @param mixed $class An object (class instance) or a string (class name).
* @param string $method The method name.
*
* @return bool
*/
public function parentMethodExists($class, $method)
{
foreach (class_parents($class) as $parent) {
if (method_exists($parent, $method)) {
return true;
}
}
return false;
}
}
class Baz extends \Bar{}
(new \Baz())->run();
// out:
// Fatal error: Uncaught Error: Call to undefined method Foo::run() in
正如您在not working case上看到的那样,Foo
类没有::run
方法
调用的类($this
)是Baz
Baz
继承的方法::从栏运行
Bar::run
调用::callParentMethodIfExists
错误地,两个helper方法都检查$this
(Baz
)并发现Baz
有一个parent::run
实际上,这两种辅助方法都应该检查当前范围(Bar
),并发现Bar
不具有parent::run
我希望这是可以理解的,有人知道一个解决办法
提前谢谢
/科顿
编辑::callParentMethodIfExists
和::parentMethodExists
也可以在Foo
上定义,或者作为trait
包含trait可能我不理解这种情况,但我会写Bar::run()
,就这么简单:
public function run()
{
if (method_exists('Foo', 'run')) {
Foo::run();
}
echo __METHOD__ . PHP_EOL;
}
您知道,Bar扩展了Foo
,不需要对父类和所有内容进行太多的调查
Bar
的子项可以重新定义方法run()
,也可以不重新定义。只要它们调用parent::run()
在他们的新定义中,调用链最终将到达调用Foo::run()
的Bar::run()
,如果它存在的话。哎哟,我的滚动手指抽筋了:-(这似乎很迂回。为什么不直接声明Foo::run
final?@AlexHowansky我不能。在实际代码中,“主机”类调用“回调”(?)。它的Phalcon\Mvc\模型可以有::beforeSave
ect。这个解决方案可能会对您有效:我需要动态地使用它。在实际代码中,这两种方法都是traits。因此它无法修复cal来自ect的位置。