Quite simply, I imagine you want to build a layout system and template slots in PHP.
A long time ago I made a lib called Phplegends/View that has it.
Only that, in a very simplified way, you can do the way I will explain below:
Create the Class View
, that represents the template that will be rendered.
class View
{
protected $sections = [];
protected $lastSection = null;
protected $layout = null;
protected $data = [];
protected $filename = null;
public function __construct($filename, array $data = [])
{
$this->filename = $filename;
$this->data = $data;
}
public function getSection($name)
{
return $this->sections[$name] ?? null;
}
public function section($name)
{
ob_start();
$this->lastSection = $name;
}
public function end()
{
$this->sections[$this->lastSection] = trim(ob_get_clean());
$this->lastSection = null;
}
public function render()
{
extract($this->data);
ob_start();
require $this->filename;
if ($this->layout) {
require $this->layout;
}
return ob_get_clean();
}
public function layout($layout)
{
$this->layout = $layout;
}
}
Next, you now need to create two files to test. Create the file templates/layout.php
and templates/teste.php
. With the following contents:
php layout.:
<!DOCTYPE html>
<html>
<head>
<title><?= $this->getSection('title') ?></title>
</head>
<body>
<?= $this->getSection('content') ?>
<footer><?= $this->getSection('footer') ?></footer>
</body>
</html>
and test.php
<?php $this->layout('templates/layout.php') ?>
<?php $this->section('footer') ?>
Meu footer bonito
<?php $this->end() ?>
<?php $this->section('content') ?>
Olá, estou na sessão "content". Meu nome é <?= $nome ?> e tenho <?= $idade ?> anos.
<?= $this->end() ?>
<?php $this->section('title') ?>
Título do meu site
<?php $this->end() ?>
Then do the test calling so:
$view = new View('templates/teste.php', [
'nome' => 'Wallace',
'idade' => 30,
]);
echo $view->render();
The result will be:
<!DOCTYPE html>
<html>
<head>
<title>Título do meu site</title>
</head>
<body>
Olá, estou na sessão "content". Meu nome é Wallace e tenho 30 anos.
<footer>Meu footer bonito</footer>
</body>
</html>
Explanation
ob_start and ob_get_end
The secret is in the ob_start()
and ob_get_end()
. The first function captures to memory everything that is going to output (the things you give echo
or writes as html
). Then when we call ob_get_end
you get all stored content and capture is terminated. For ease, we always take the name and put in the variable $sections
with a key and a value captured until the call of end
.
Note that in render
we call again the ob_start()
. This is for the content of require
not be displayed, but just captured. Even you calling ob_start
several times, is considered just the stretch where you called ob_start
until the call of ob_get_end
. PHP internally stacks until you "close" all ob_start
with the call of ob_get_end
.
Remembering that this example was the least, only to understand the functioning. You can separate the code better if you feel it necessary, as I did in my library.
Extract
This function transforms the values passed into a array
variables. How we use require
within the method render
, variables will be available in your "template".
So second, in our case, the value ['nome' => 'Wallace', 'idade' => 30]
were transformed to $nome
and $idade
.
Access to $this
How our template was called through the function require
, everything inside the class View
will be accessible in templates/layout.php
and templates/teste.php
, including the variable $this
. That’s why in my library I created the class Context
, to isolate the scope of templates for the instance of Context
, since I had things in View
who did not want it to be accessible by the template. But in this case, it is only an idea, it is up to you to implement this or otherwise.
NOTE: My section
is equivalent to its start
, followed by end
. And mine getSection
is equivalent to its section
. Feel free to change the names =)
Do you already have more or less an idea? Have you done something? I’ve developed one PHP view system, and for that I used
ob_start
.– Wallace Maxters
It is important to provide a [mcve] for your question. Click [Edit] and add more information. The question is half vacant...
– Wallace Maxters
I found a reference to what I’m trying to explain: https://platesphp.com/templates/sections/ Thanks
– Philipe Silva
Exactly what I said. You can use the function
ob_start()
. It captures all output coming from the code. Then you can recover it withob_get_end()
.– Wallace Maxters
What you really want is to know how to work with "section" system in a php template.
– Wallace Maxters
Thank you for clarifying my doubt, could you give me a simple example ?
– Philipe Silva
Hello, young man. I made a very simple example for you to understand.
– Wallace Maxters