Reputation: 49
I'am really very new to PHP.
I have this code:
<?php cms_loop('500');?>
<div class="item">
<p class="contents"></p>
</div>
<?php cms_loop_end('500');?>
I want to output everything between cms_loop and cms_loop_end functions.
I do it this way:
function cms_loop($id){
ob_start();
echo ob_get_contents();
}
and
function cms_loop_end(){
ob_end_flush();
}
But that's not working. Any help appreciated
Upvotes: 2
Views: 1077
Reputation: 12078
Below you can find the working code:
<?php
/**
* Start buffering
* @param $id
*/
function cms_loop($id){
ob_start();
}
/**
* Output everything buffered
*/
function cms_loop_end(){
ob_end_flush();
}
?>
<?php cms_loop('500');?>
<div class="item">
<p class="contents">Hello from buffered content</p>
</div>
<?php cms_loop_end('500');?>
Please note that I removed the echo ob_get_contents();
from your cms_loop()
function.
Demo: https://onecompiler.com/php/3wuscawt7 (There is an option to run without account)
Upvotes: 2
Reputation: 665
I'm assuming you're trying to achieve some kind of template rendering as you apparently trying to render some piece of HTML for later use. For that to happen, PHP needs to be aware of that piece. In your example, though, both PHP and HTML co-exist side by side without either side having any knowledge about the other. Your HTML isn't part of PHP's realm yet.
Let's change that.
The piece of HTML you've given is often called a partial, i.e. something that's meant to be part of something bigger. Like a sidebar being a conceptual part of an index.html file, but not a physical one unless included:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>Welcome!</h1>
<!-- Partial -->
<?php include_once('sidebar.html') ?>
</body>
</html>
So let's take a similar approach and factor out the HTML into its own file first:
<div class="item">
<p class="contents"></p>
</div>
partial.html.php
Now we need to find a way to transfer this piece of HTML into the realm of PHP. The simplest approach would be to read it and assign it to a variable:
$html = file_get_contents('partial.html.php');
Let's get back to your function for a second, because now you could do:
function cms_loop($html){
echo $html;
}
I have taken $id
off of the list of the function's parameters, mostly because of the following reasons:
Though let's ponder the last one a bit. Wouldn't it be nice if we could pass data into our template, for example to dynamically change the classes we have assigned to both HTML elements?
It would most definitely be nice, and it's possible, too - what we need for that is just a little bit of output buffering. But first, let's change our template to meet our new needs:
<div class="<?php echo $class_outer ?>">
<p class="<?php echo $class_inner ?>"></p>
</div>
So we'll have to define both values up front. But we might end up with a lot more template variables once we get the hang of it, so let's best use an array as a container to store our current and any future values:
$data = [
'class_outer' => 'item',
'class_inner' => 'contents',
];
Next, we'll need some function to render our template with the values we just defined, so it'll need two parameters: The path to the template file and our data array. Also, we want it to return our rendered template. That said, it'll probably look like this:
function render(string $template_path, array $data): string {
if (!is_file($template_path)) {
return false; // Or some better error handling
}
// Let's have some sugar in our templates: Import all indexes
// of our data array as variables into the current scope so
// they can easily be accessed by the template we're about to render.
//
// In other words, we now have two new variables:
//
// - $class_outer (extracted from $data['class_outer'])
// - $class_inner (extracted from $data['class_inner'])
//
// Cf. https://www.php.net/manual/en/function.extract.php
extract($data);
// Start output buffering
ob_start();
// Render template
include $template_path; // By including it, it has access to all
// variables defined in the current scope, i.e.
// inside this very function - like the variables
// we just extracted from $data
$rendered = ob_get_contents(); // Assign all output to a variable, so we can return it.
// End output buffering
ob_end_clean();
return $rendered;
}
Now, we can call that like:
$rendered = render('templates/partial.html.php', $data);
Upvotes: 2