EDIT: As requested by @hakre, here is a simplified version of the parent class. See below that for the full, original question.
class WebsitePage {
protected $name;
protected $slug;
protected $heading;
protected $intro;
protected $content;
// constructor and other unrelated functions, including name()
// which just spits out a simple string passed into the constructor,
// and heading(), which wraps that in a <h1> tag.
...
public function slug() {
return isset($this->slug) ? $this->slug : strtolower(
str_replace(array(' ', '/'), '-', $this->name));
}
public function content() {
return isset($this->content) ? $this->
content : $this->get_template();
}
protected function get_template() {
ob_start();
include(__DIR__ . '/templates/' . (!empty($this->
slug()) ? $this->slug() : $this->name) . '.php');
$content = ob_get_contents();
ob_end_clean();
return $this->intro() . $content;
}
}
ORIGINAL: Similar to this question, I am having trouble getting class inheritance (specifically function overriding) to work the way that every PHP resource specifies.
Parent class:
class WebsitePage {
protected $name;
protected $slug;
protected $heading;
protected $intro;
protected $content;
public function __construct($name, $slug = null, $heading = null, $intro = null, $content = null) {
$this->name = $name;
$this->slug = $slug;
$this->heading = $heading;
$this->intro = $intro;
$this->content = $content;
}
public function name() {
return $this->name;
}
public function slug() {
return isset($this->slug) ? $this->slug : strtolower(
str_replace(array(' ', '/'), '-', $this->name));
}
public function heading() {
return isset($this->heading) ? $this->
heading : "<h1>$this->name</h1>";
}
public function intro() {
return '<div class="page-intro">' . (!isset($this->intro) ? $this->
heading : "$this->heading<p>$this->intro</p>") . '</div>';
}
public function content() {
return isset($this->content) ? $this->
content : $this->get_template();
}
protected function get_template() {
ob_start();
include(__DIR__ . '/templates/' . (!empty($this->
slug()) ? $this->slug() : $this->name) . '.php');
$content = ob_get_contents();
ob_end_clean();
return $this->intro() . $content;
}
}
Child class:
class WebsiteServicePage extends WebsitePage {
public function __construct($name, $slug = null, $heading = null, $intro = null, $content = null) {
parent::__construct($name, $slug, $heading, $intro, $content);
}
public function slug() {
return 'our-services/' . parent::slug();
}
public function heading() {
return isset($this->heading) ? $this->
heading : "<h2>$this->name</h2>";
}
}
Instantiation:
$servicePages = array(
new WebsiteServicePage('Tree Lopping'),
new WebsiteServicePage('Land Clearing')
...more service page instantiations
);
foreach ($servicePages as $servicePage) {
echo $servicePage->content();
}
Which on each iteration of the loop results in the parent class' content()
being called, which calls its own get_template()
, which calls its own slug()
and therefore omits /our-services
from the final page slug. This means that get_template()
can't find the correct template files, since they exist in the our-services
directory.
I could simply put all templates in the same dir to get around this issue, but I feel as though I must be misunderstanding something fundamental about PHP class inheritance. Although as mentioned before, every single PHP resource that I've been able to find has suggested that what I have done should work!
So what gives? MTIA! :-)
P.S. StackOverflow is suggesting that I should add some more non-code content to my question, so for those who care, this is for a website that I'm building for a client who runs a tree lopping/arborism business. They provide all kinds of tree-related services, so the child WebsiteServicePage
class is very important. I'd also like to reuse this model (with some obvious modifications) on any sites that I dev in the future, so I really need to know what I'm doing wrong here! Thanks again :-)