Home > Back-end >  Traversing up a PHP class structure by calling parent functions recursively
Traversing up a PHP class structure by calling parent functions recursively

Time:01-10

While building an object-based menu component i ran into a problem.

Imagine:

abstract class key {}
class key_main extends key {}
class key_submenu extends key_main {}
class key_navpoint extends key_submenu {}

These menu items can render themselves:

abstract class key {
    public function render(){
        return template::get('key', '/tpl/menu/');
    }
}

The according templates are stored in a structurally similar scheme:

/tpl/menu/main/template.key.php
/tpl/menu/main/submenu/template.key.php
/tpl/menu/main/submenu/navpoint/template.key.php

In order for the render functions to access the correct templates, i want to introduce a function buildTemplatePath() that basically calls itself for inherited-from class up the tree, chaining classnames together:

abstract class key {
    public function buildTemplatePath(){
        return get_class($this) . '/' . parent::buildTemplatePath();
    }
}

This function should return the correct path:

$navpoint=new key_navpoint();
$path=$navpoint->buildTemplatePath();
/* $path should be 'main/submenu/navpoint' */

The problem is that this only works if i place the buildTemplatePath() function within each child class separately. Since it contains the same code, it seems kind of a shady workaround to me, to do that.

Therefore my question is:

How do i modify buildTemplatePath() so that it works as desired without having to be defined in each subclass?

I tried various things, including using get_parent_class($this), but i cannot get this to work.

CodePudding user response:

Use recursion, but you may manually remove the "key_" and namespace prefixes returned from get_parent_class and get_class.

abstract class key {
    public function buildTemplatePath(){
        return self::buildTemplatePathRecursion(get_class($this));
    }
    private static function buildTemplatePathRecursion(string $clz){
        $parentClz = get_parent_class($clz);
        return $parentClz ?
            self::buildTemplatePathRecursion($parentClz).'/'.$clz :
            '';
    }
}
  • Related