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 :
'';
}
}