I'm writing a class - called MenuBuilder
- in PHP 7 which is intended to build navigation menus in a web application.
The way in which the class works is by building up an output buffer which holds the markup for the menus.
It starts off by declaring an empty variable inside class MenuBuilder
:
private $output_buffer = '';
There is a method to add to it:
protected function add_to_output_buffer($input = '') {
if ($input !== '') {
$this->output_buffer .= $input;
}
}
And a method to display the menu markup:
public function render() {
echo $this->output_buffer;
}
So far quite straightforward. Here's the problem... When I add a link to the menu I use this method:
public function add_menu_item($item) {
$this->menu_items[] = $item;
}
This builds up an array ($this->menu_items
) and there is then another method which cycles through the items in it to add them to the output buffer. It's quite long but a shortened version of it is here:
public function create_links() {
foreach ($this->menu_items as $item) {
$output = '';
$output = '<a href="'.$item['link'].'">'.$item['text'].'</a>';
$this->add_to_output_buffer($output);
}
}
There is quite a lot of logic in create_links()
because various classes and other things get applied to the links, but essentially it has to work like this because it needs to loop through the full array of links.
The problem: If I want to add random HTML at any point in the menu, I have a function to do this:
public function add_misc_html($html = '') {
$this->output_buffer .= $html;
}
But in my script which uses these functions, it doesn't know the order in which things are being called. An example:
$MenuBuilder = new MenuBuilder;
$MenuBuilder->add_menu_item(['text' => 'Link 1', 'link' => '#']);
$MenuBuilder->add_menu_item(['text' => 'Link 2', 'link' => '#']);
$MenuBuilder->add_misc_html('<h1>testing add_misc_html</h1>');
$MenuBuilder->add_menu_item(['text' => 'Link 3', 'link' => '#']);
$MenuBuilder->create_links();
$MenuBuilder->render();
So the problem is that the desired output is:
<a href="#">Link 1</a>
<a href="#">Link 2</a>
<h1>testing add_misc_html</h1>
<a href="#">Link 3</a>
But this won't work, because when I call create_links()
it's not aware of add_misc_html
and where this is called in the overall structure of the calls to MenuBuilder
What ways can I achieve the desired output? Please note that add_misc_html()
needs to work anywhere it gets called, prior to render()
. There is a whole load of other stuff in the class to open the menu and close it, so it needs to be able to modify the $this->output_buffer
at any point.