PHP检查父项是否存在(如果继承)(当前范围而不是$ this)

时间:2017-03-23 19:11:40

标签: php inheritance parent

我希望我能清楚地写下来

案例:

我有 base Foo

Foo 可以拥有方法(例如) ::run

另一个班级Bar扩展Foo并拥有自己的方法::runBar (以及编写Bar的开发人员不知道父Foo 是否会方法::run

这就是Bar想要在parent上调用当前方法的原因。

辅助方法::callParentMethodIfExists应该完成其工作并检查$method上是否存在parent

到目前为止一切顺利:

  • 致电Bar::run
  • Bar::run来电::callParentMethodIfExists
  • ::callParentMethodIfExists调用parent::run(如果存在)。

问题:

如果现在某个班级Baz延伸BarBaz 则使用::run方法:

  • 调用继承自Baz::run
  • Bar
  • 执行Bar::run
  • Bar::run来电::callParentMethodIfExists
  • ::callParentMethodIfExists调用::parentMethodExists并检查(这就是问题) $thisBaz)是否有父方法{{1} }

所以事实证明这是真的,因为::run有一个Baz(即parent::run ofc)但是这不是我应该从中检查它的范围

简而言之

帮助方法Bar::run::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

正如您在 not not case 上看到的那样,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 类没有Foo方法。

被叫类(::run)是$this

来自Baz

Baz继承方法::run

Bar来电Bar::run

两个辅助方法错误地检查::callParentMethodIfExists$this)并找出 Baz有一个Baz

实际上,两个辅助方法应该检查当前范围parent::run)并找出 Bar 是否有Bar

我希望这是可以理解的,有人知道解决方案。

提前致谢!

/ cottton

编辑 parent::run::callParentMethodIfExists也可以在::parentMethodExists上定义或包含在Foo中。

1 个答案:

答案 0 :(得分:0)

也许我不了解情况,但我会写Bar::run()就像那样简单:

public function run()
{
    if (method_exists('Foo', 'run')) {
        Foo::run();
    }

    echo __METHOD__ . PHP_EOL;
}

你知道Bar extends Foo,没有必要对父类和所有东西进行如此多的调查。

Bar的孩子可能会重新定义方法run(),或者他们可能不会。只要他们在新定义中调用parent::run();,调用链最终将会Bar::run()调用Foo::run()(如果存在)。