Rozbudowa TemplateEngine – dodanie metody renderTemplate, która będzie renderować prawdziwy template engine. Zaczynamy!

Tworzymy plik sth2.php:

<h1>{{ $site_name }}</h1>
<p> Hello {{ $name }}</p>

Ok, tworzymy metodę renderTemplate:

class TemplateEngine
{
  
  //(...)

  public function renderTemplate(string $template, array $data = []){

    extract($data, EXTR_SKIP);
    extract($this->globalTemplateData, EXTR_SKIP);

    $content = file_get_contents($this->resolve($template));
    var_dump($content);
    

  }

  //(...)
}

$template = new TemplateEngine(__DIR__);
$template->addGlobal('site_name', 'MyApp');
echo $template->renderTemplate('sth2.php', ['name' => 'John']);

Na razie zaciągnęliśmy zawartość pliku – teraz spróbujmy poddać go wyrażeniu regularnemu:

class TemplateEngine
{
  
  //(...)

  public function renderTemplate(string $template, array $data = []){

    extract($data, EXTR_SKIP);
    extract($this->globalTemplateData, EXTR_SKIP);

    $content = file_get_contents($this->resolve($template));
    var_dump($content);
    
    $pattern = '/\{\{\s*(\$.*?)\s*\}\}/';
    preg_match($pattern, $content, $matches);
    print_r($matches);

  }

}

Teraz musimy jeszcze zamienić wyrażenie regularne na co trzeba:

class TemplateEngine
{
  
   //(...)

  public function renderTemplate(string $template, array $data = []){

    extract($data, EXTR_SKIP);
    extract($this->globalTemplateData, EXTR_SKIP);

    $content = file_get_contents($this->resolve($template));

    $pattern = '/\{\{\s*(\$.*?)\s*\}\}/';
    $content = preg_replace($pattern, "<?=$1; ?>", $content);
    var_dump($content);
  }
 
}

Możemy zrobić var_dump, ale niewiele zobaczymy – z jednej strony PHP zostanie przeparsowany, z drugiej zmienne te nie istnieją w danym kontekście. Musimy jeszcze sth2.php nieco zmienić:

<?php ?>
<h1>{{ $site_name }}</h1>
<p> Hello {{ $name }}</p>

Ok, nie musimy – ale chciałem pokazać, co za chwilę zrobi funkcja eval:

class TemplateEngine
{
  //(...)

  public function renderTemplate(string $template, array $data = []){

    extract($data, EXTR_SKIP);
    extract($this->globalTemplateData, EXTR_SKIP);

    $content = file_get_contents($this->resolve($template));

    $pattern = '/\{\{\s*(\$.*?)\s*\}\}/';
    $content = preg_replace($pattern, "<?=$1; ?>", $content);
    
    eval( '?>' . $content );

  }

  //(...)
}

Eval jak działa to domyślnie otwiera tag <?php i nie patrzy na nic. Trzeba więc ten domyślny „domknąć”. A w plikach templatki używać normalnie, według potrzeb.

Ten zbędny zawsze zostanie domknięty. Teraz możemy wypróbować nasz engine:

<?php 

class TemplateEngine
{
  //(...)
}

$template = new TemplateEngine(__DIR__);
$template->addGlobal('site_name', 'MyApp');
echo $template->renderTemplate('sth2.php', ['name' => 'John']);

Engine będziemy rozbudowywać.