Шаблонизатор на PHP

Форум для тех кто начинает осваивать язык php.
Аватара пользователя
Slash
Администратор
Сообщения: 2029
Поблагодарили: 62 раза

Шаблонизатор на PHP

Сообщение Slash » Вс июл 26, 2015 10:24 am

Сегодня, с утра (для практики) набросал простой шаблонизатор на PHP (если так его можно назвать :oops: ). В шаблоне переменные выглядят так [title] (квадратные скобки).
Шаблонизатор работает только с переменными, функции, конструкции и прочий php код не распознаются скриптом и будут выводится, как обычный текст. Скрипт создает кэш шаблонов.
Пример шаблона:

Код: Выделить всё

<html>
<
title>[title]</title>
[
content]
</
html>

Переменные для шаблона пишутся в массив:

Код: Выделить всё

$tpl = array(
    '[title]'   => 'Home Page',
    '[content]' => 'Content Page'
);

Подключение шаблона делается пользовательской функцией template():

Код: Выделить всё

template($tpl, 'tpl_name');

Внутрь функции вставляется языковой массив ($tpl) и название шаблона, без формата файла.
Сам скрипт шаблонизатора выглядит так:

Код: Выделить всё

# Функция Шаблонизатор PHP
function template($tpl, $html)                                            
{
    $script = basename($_SERVER['REQUEST_URI']); # Текущая страница
    $dir_cache = 'cache/';    # Директория хранения кэша
    $dir_tpl = 'html/';     # Директория хранения шаблонов
    $ext = '.html';         # Расширение файлов шаблона    
    # Проверяем права на папку cache, должны быть 777, если нет, устанавливаем 777
    if (!chmod($dir_cache, 0777)) 
    
{
        chmod($dir_cache, 0777);
    }
    # Проверка шаблона в кэш
    if (file_exists($dir_cache . $script))
    {
        include($dir_cache . $script);
    }
    else
    
{
        $html = file_get_contents($dir_tpl . $html . $ext);                # Получаем содержимое шаблона
        $html = str_replace(array_keys($tpl), array_values($tpl), $html);  # Меняем значение на переменные в шаблоне
        echo $html;              # Выводим результат на экран

        $file = fopen($dir_cache . $script, 'w-'); # Создаем новый, пустуй файл
        fwrite($file, $html); # Записываем код в файл
        fclose($file);        # Закрываем файл
    }
}

Надеюсь, кому ни будь пригодится.

Читайте ещё:
Шаблоны в PHP
Шаблоны для PHP (Делать или нет?)
Шаблонизатор на php
Реклама
Аватара пользователя
Slash
Администратор
Сообщения: 2029
Поблагодарили: 62 раза

Re: Шаблонизатор на PHP

Сообщение Slash » Вс июл 26, 2015 1:01 pm

Если есть необходимость обновлять кэшированные шаблоны, через какое то время, то дописываем после:

Код: Выделить всё

        include($dir_cache $script); 

следующий код:

Код: Выделить всё

        $filemtime date('H:i d.m.Y'strtotime(date('H:i d.m.Y'filemtime($dir_cache $script)) . ' + 60 min'));
        if (
$filemtime <= date('H:i d.m.Y')) 
        {
            
unlink($dir_cache $script);
        } 

На данный момент установлено обновление на один час (60 минут). Изменить время обновления можно в этой части кода: ' + 60 min'.
Обновление файла происходит по истечении заданного времени и обращении к скрипту.
Проверка на существование самих шаблонов (.html) - перед:

Код: Выделить всё

        $html file_get_contents($dir_tpl $html $ext);                # Получаем содержимое шаблона 

добавить:

Код: Выделить всё

        if (!file_exists($dir_tpl $html $ext))
        {
            exit(
'No Template');
        } 
Аватара пользователя
Slash
Администратор
Сообщения: 2029
Поблагодарили: 62 раза

Re: Шаблонизатор на PHP

Сообщение Slash » Чт июл 30, 2015 7:13 am

Поправил код, теперь на экран выводятся шаблоны только из кэша. Добавил обработку echo / if / foreach, вставить в <!-- ... --> (по просьбе Шаблонизатор на php). С функцией include пока ещё не разобрался. Исправил несколько недочетов.

Код: Выделить всё

<?php
# Функция Шаблонизатор PHP
function template($template, $tpl)                                       
{
    $url = basename($_SERVER['REQUEST_URI']); # Текущий URL страницы
    $dir_cache = 'cache/';                      # Директория хранения кэша
    $dir_tpl =   'tpl/';                      # Директория хранения шаблонов
    $ext_tpl =   '.html';                     # Расширение файлов шаблона
    $ext_cache = '.php';                      # Расширение файлов кэша

    # Проверка шаблона в кэше
    if (file_exists($dir_cache . $url . $ext_cache))
    {
        # Определение даты создания файла шаблона в кэше
        $filemtime = date('H:i d.m.Y', strtotime(date('H:i d.m.Y', filemtime($dir_cache . $url . $ext_cache)) . ' + 180 min'));
        if ($filemtime <= date('H:i d.m.Y'))
        {
            unlink($dir_cache . $url . $ext_cache);
        }        
    
}    
    
    
# Проверка шаблона в кэше
    if (file_exists($dir_cache . $url . $ext_cache))
    {
        include($dir_cache . $url . $ext_cache);        
    
}
    else
    
{
        if (!file_exists($dir_tpl . $tpl . $ext_tpl)) # Проверка наличия шаблона
        {
            exit('No Template');
        }
        
        ob_start
();                          # Включение буферизации
        include($dir_tpl . $tpl . $ext_tpl); # Подключение шаблона
        $cache_tpl = ob_get_contents();      # Получение содержимого буфера
        ob_end_clean();                         # Отключение и очистка буфера

        $code = array(
            # Обработка переменных
            '/\<!-- ECHO (.*?) \-->/'     => '<?php echo $1; ?>',    
        
            
# Обработка условия (IF / ELSEIF / ELSE / ENDIF)
            '/\<!-- IF (.*?) \-->/'       => '<?php if $1: ?>',
            '/\<!-- ELSEIF (.*?) \-->/'   => '<?php elseif $1: ?>', 
            
'/\<!-- ELSE \-->/'           => '<?php else: ?>',
            '/\<!-- ENDIF \-->/'          => '<?php endif; ?>',
            
            
# Обработка цикла (FOREACH / ENDFOREACH)
            '/\<!-- FOREACH (.*?) \-->/'  => '<?php foreach $1: ?>',    
            
'/\<!-- ENDFOREACH \-->/'     => '<?php endforeach; ?>'
        );
        
        $cache_tpl 
= str_replace(array_keys($template), array_values($template), $cache_tpl); # Замена переменных на значение        
        $cache_tpl = preg_replace(array_keys($code), array_values($code), $cache_tpl);        # Замена кода в шаблоне

        $file = fopen($dir_cache . $url . $ext_cache, 'w-');  # Создание нового файла
        fwrite($file, $cache_tpl);                            # Запись содержимого буфера в файл
        fclose($file);                                        # Закрытие файла
        
        include
($dir_cache . $url . $ext_cache);              # Подключение файла кэша    
    }    
}
Аватара пользователя
Slash
Администратор
Сообщения: 2029
Поблагодарили: 62 раза

Re: Шаблонизатор на PHP

Сообщение Slash » Вт авг 04, 2015 8:43 am

Новая версия шаблонизатора.
Переделал вид кода, теперь шаблонизатор работает в фигурных скобках, например {echo $name}, мне показалось, что так лучше, чем <!-- echo $name -->, символов используется меньше, да и красивее.
Добавил обработчик {include name_file}.
Убрал автоматическое удаление кэшированного шаблона.
Исправил небольшие недочеты.

Код: Выделить всё

<?php
/*
    DANFA Функция template($tpl, $template);
    * (1 параметр) $tpl – массив
    * (2 параметр) $template – имя подключаемого шаблона, без расширения, например index.
*/

# Функция Шаблонизатор
function template($tpl, $template)                                            
{
    $page = basename($_SERVER['SCRIPT_FILENAME']); # Текущий скрипт
    $dir_cache = 'cache/';                           # Директория хранения кэша
    $dir_tpl =   'tpl/html/';                      # Директория хранения шаблонов
    $ext_cache = '.php';                           # Расширение файлов кэша
    $ext_tpl =   '.html';                          # Расширение файлов шаблона
    
    
# Проверка шаблона в кэше
    if (file_exists($dir_cache . $page . $ext_cache))
    {
        include($dir_cache . $page . $ext_cache);        
    
}
    else
    
{
        if (!file_exists($dir_tpl . $template . $ext_tpl)) # Проверка наличия шаблона
        {
            exit('No Template: <strong>' . $template . $ext_tpl . '</strong>');
        }
        
        ob_start
();                               # Включение буферизации
        include($dir_tpl . $template . $ext_tpl); # Подключение шаблона        
        $cache_tpl = ob_get_contents();           # Получение содержимого буфера        
        ob_end_clean();                              # Отключение и очистка буфера    
        
        
# Обработка INCLUDE
        if (preg_match('/\{include (.*?)\}/', $cache_tpl))
        {
            function incl($cache_tpl, $dir_tpl, $ext_tpl)
            {
                preg_match_all('/\{include (.*?)\}/', $cache_tpl, $include_array);
                foreach ($include_array[1] as $key => $incl)
                {
                    if (file_exists($dir_tpl . $incl . $ext_tpl))
                    {
                        $incl_tpl     = '/\{include ' . $incl . '}/';
                        $incl_replace = file_get_contents($dir_tpl . $incl . $ext_tpl);
                        $cache_tpl    = preg_replace($incl_tpl, $incl_replace, $cache_tpl);
                    }
                    else
                    
{
                        exit('No Template: <strong>' . $incl . $ext_tpl . '</strong>');
                    }
                }
                if (preg_match('/\{include (.*?)\}/', $cache_tpl))
                {
                    $cache_tpl = incl($cache_tpl, $dir_tpl, $ext_tpl);
                }
                return $cache_tpl;
            }
            $cache_tpl = incl($cache_tpl, $dir_tpl, $ext_tpl);
        }
        # END Обработка INCLUDE    

        $code = array(
            # Вывод переменных (ECHO)
            '/\{echo (.*?)\}/'    => '<?php echo $1; ?>',        
        
            
# Обработка условия (IF / ELSEIF / ELSE / ENDIF)
            '/\{if (.*?)\}/'      => '<?php if ($1): ?>',
            '/\{elseif (.*?)\}/'  => '<?php elseif ($1): ?>', 
            
'/\{else}/'           => '<?php else: ?>',
            '/\{endif}/'          => '<?php endif; ?>',
            
            
# Обработка цикла (FOREACH / ENDFOREACH)
            '/\{foreach (.*?)\}/' => '<?php foreach ($1): ?>',    
            
'/\{endforeach}/'     => '<?php endforeach; ?>'
        );
        
        $cache_tpl 
= preg_replace(array_keys($code), array_values($code), $cache_tpl);  # Замена кода в шаблоне

        $file = fopen($dir_cache . $page . $ext_cache, 'w-');  # Создание нового файла
        fwrite($file, $cache_tpl);                             # Запись содержимого буфера в файл
        fclose($file);                                         # Закрытие файла
        
        include
($dir_cache . $page . $ext_cache);              # Подключение файла кэша    
    }    
}
Аватара пользователя
Slash
Администратор
Сообщения: 2029
Поблагодарили: 62 раза

Re: Шаблонизатор на PHP

Сообщение Slash » Чт авг 06, 2015 9:16 pm

Я подумал о том, что на одном сайте могут быть несколько разных стилей, по этому добавил переменную $style_tpl, которая содержит в себе название стиля. Теперь в кэше будут сохраняться шаблоны с прификсом, названием стиля, что бы не получить ошибки при использовании нескольких стилей. Так же я подумал о том, что не все страницы надо заносить в кэш, порой достаточно всего одной, что бы в дальнейшем она заменяла тысячи, так как кроме текста на страницах ни чего не меняется, например такая страница topic.php?p=3482 и topic.php?p=8234 ни чем ни отличаются, кроме текста. А иногда один файл вывод несколько разных страниц, например форму регистрации и форму входа, пример url user.php?p=reg и user.php?=input, тут необходимо сохранять шаблон в двух разных видах. Подумав об этом я добавил выключатель REQUEST URI (on/off), если необходимо сохранять шаблон конкретной страницы, пишем on, если этого не нужно, пишем off в вызове функции, например так:

Код: Выделить всё

template($tpl, 'index', 'off');

Сам сценарий шаблонизатора:

Код: Выделить всё

<?php
/*
    DANFA Функция template($tpl, $template, $request_uri);
    * (1 параметр) $tpl – массив
    * (2 параметр) $template – имя подключаемого шаблона, без расширения, например index.
    * (3 параметр) $request_uri - включение/отключение REQUEST URI
    * * on - включено
    * * off - выключено
*/

# Функция Шаблонизатор
function template($tpl, $template, $request_uri)                                            
{
    if ($request_uri == 'on')
    {
        $page = basename($_SERVER['REQUEST_URI']);     # Текущий URL страницы    
    }
    else
    
{
        $page = basename($_SERVER['SCRIPT_FILENAME']); # Текущий скрипт    
    }
    
    $style_tpl 
= 'standard';                       # Название стиля
    $dir_cache = 'cache/';                           # Директория хранения кэша
    $dir_tpl =   'style/' . $style_tpl . '/html/'; # Директория хранения шаблонов
    $ext_cache = '.php';                           # Расширение файлов кэша    
    $ext_tpl =   '.html';                          # Расширение файлов шаблона

    # Проверка шаблона в кэше
    if (file_exists($dir_cache . $style_tpl . '_' . $page . $ext_cache))
    {
        include($dir_cache . $style_tpl . '_' . $page . $ext_cache);        
    
}
    else
    
{
        if (!file_exists($dir_tpl . $template . $ext_tpl)) # Проверка наличия шаблона
        {
            exit('No Template: <strong>' . $template . $ext_tpl . '</strong>');
        }
        
        ob_start
();                               # Включение буферизации
        include($dir_tpl . $template . $ext_tpl); # Подключение шаблона        
        $cache_tpl = ob_get_contents();           # Получение содержимого буфера        
        ob_end_clean();                              # Отключение и очистка буфера    
        
        
# Обработка INCLUDE
        if (preg_match('/\{include (.*?)\}/', $cache_tpl))
        {
            function incl($cache_tpl, $dir_tpl, $ext_tpl)
            {
                preg_match_all('/\{include (.*?)\}/', $cache_tpl, $include_array);
                foreach ($include_array[1] as $key => $incl)
                {
                    if (file_exists($dir_tpl . $incl . $ext_tpl))
                    {
                        $incl_tpl     = '/\{include ' . $incl . '}/';
                        $incl_replace = file_get_contents($dir_tpl . $incl . $ext_tpl);
                        $cache_tpl    = preg_replace($incl_tpl, $incl_replace, $cache_tpl);
                    }
                    else
                    
{
                        exit('No Template: <strong>' . $incl . $ext_tpl . '</strong>');
                    }
                }
                if (preg_match('/\{include (.*?)\}/', $cache_tpl))
                {
                    $cache_tpl = incl($cache_tpl, $dir_tpl, $ext_tpl);
                }
                return $cache_tpl;
            }
            $cache_tpl = incl($cache_tpl, $dir_tpl, $ext_tpl);
        }
        # END Обработка INCLUDE    

        $code = array(
            # Вывод переменных (ECHO)
            '/\{echo (.*?)\}/'    => '<?php echo $1; ?>',        
        
            
# Обработка условия (IF / ELSEIF / ELSE / ENDIF)
            '/\{if (.*?)\}/'      => '<?php if ($1): ?>',
            '/\{elseif (.*?)\}/'  => '<?php elseif ($1): ?>', 
            
'/\{else}/'           => '<?php else: ?>',
            '/\{endif}/'          => '<?php endif; ?>',
            
            
# Обработка цикла (FOREACH / ENDFOREACH)
            '/\{foreach (.*?)\}/' => '<?php foreach ($1): ?>',    
            
'/\{endforeach}/'     => '<?php endforeach; ?>'
        );
        
        $cache_tpl 
= preg_replace(array_keys($code), array_values($code), $cache_tpl);  # Замена кода в шаблоне

        $file = fopen($dir_cache . $style_tpl . '_' . $page . $ext_cache, 'w-');        # Создание нового файла
        fwrite($file, $cache_tpl);                                                      # Запись содержимого буфера в файл
        fclose($file);                                                                  # Закрытие файла
        
        include
($dir_cache . $style_tpl . '_' . $page . $ext_cache);                    # Подключение файла кэша    
    }    
}
Аватара пользователя
Slash
Администратор
Сообщения: 2029
Поблагодарили: 62 раза

Re: Шаблонизатор на PHP

Сообщение Slash » Чт авг 20, 2015 7:53 am

Кое что поправил, теперь в функцию достаточно вставить только название шаблона:

Код: Выделить всё

template('index'); 

Если в адресе страничке будет знак &, то шаблонизатор обрежет все что находится за этим знаком и сам знак.
Если есть необходимость передать переменную в функцию шаблонизатор, то сделать это можно при помощи global (Re: Как передать переменную в пользовательскую функцию PHP)

Код: Выделить всё

<?php
/*
    DANFA http://danfa.org
    Функция template($subject);
    * $subject – имя подключаемого шаблона, без расширения, например index.
    Файл template.php
*/

# Функция Шаблонизатор
function template($subject)                                            

    
# URL страницы
    
$page basename($_SERVER['REQUEST_URI']);
    if (
preg_match('/\&/'$page))
    {
        
$explode explode('&'$page);
        
$page $explode[0];
    }
    
# END URL страницы
    
    
$style_tpl 'standard';                       # Название стиля
    
$dir_cache 'cache/';                           # Директория хранения кэша
    
$dir_tpl =   'style/' $style_tpl '/html/'# Директория хранения шаблонов    
    
    # Проверка шаблона в кэше
    
if (file_exists($dir_cache $style_tpl '_' $page PHP))
    {
        include(
$dir_cache $style_tpl '_' $page PHP);        
    }
    else
    {
        if (!
file_exists($dir_tpl $subject HTML)) # Проверка наличия шаблона
        
{
            exit(
'No Template: <strong>' $subject HTML '</strong>');
        }
        
        
ob_start();                               # Включение буферизации
        
include($dir_tpl $subject HTML);      # Подключение шаблона        
        
$cache_tpl ob_get_contents();           # Получение содержимого буфера        
        
ob_end_clean();                              # Отключение и очистка буфера    
        
        # Обработка INCLUDE
        
if (preg_match('/\{include (.*?)\}/'$cache_tpl))
        {
            function 
incl($cache_tpl$dir_tpl)
            {
                
preg_match_all('/\{include (.*?)\}/'$cache_tpl$include_array);
                foreach (
$include_array[1] as $key => $incl)
                {
                    if (
file_exists($dir_tpl $incl HTML))
                    {
                        
$incl_tpl     '/\{include ' $incl '\}/';
                        
$incl_replace file_get_contents($dir_tpl $incl HTML);
                        
$cache_tpl    preg_replace($incl_tpl$incl_replace$cache_tpl);
                    }
                    else
                    {
                        exit(
'No Template: <strong>' $incl HTML '</strong>');
                    }
                }
                if (
preg_match('/\{include (.*?)\}/'$cache_tpl))
                {
                    
$cache_tpl incl($cache_tpl$dir_tpl);
                }
                return 
$cache_tpl;
            }
            
$cache_tpl incl($cache_tpl$dir_tpl);
        }
        
# END Обработка INCLUDE    

        
$code = array(
            
'/\{echo (.*?)\}/'    => '<?php echo $1; ?>',
            
'/\{if (.*?)\}/'      => '<?php if ($1): ?>',
            
'/\{elseif (.*?)\}/'  => '<?php elseif ($1): ?>'
            
'/\{else}/'           => '<?php else: ?>',
            
'/\{endif}/'          => '<?php endif; ?>',
            
'/\{foreach (.*?)\}/' => '<?php foreach ($1): ?>',    
            
'/\{endforeach}/'     => '<?php endforeach; ?>'
        
);
        
        
$cache_tpl preg_replace(array_keys($code), array_values($code), $cache_tpl);  # Замена кода в шаблоне

        
$file fopen($dir_cache $style_tpl '_' $page PHP'w-');               # Создание нового файла
        
fwrite($file$cache_tpl);                                                      # Запись содержимого буфера в файл
        
fclose($file);                                                                  # Закрытие файла
        
        
include($dir_cache $style_tpl '_' $page PHP);                           # Подключение файла кэша    
    
}    
}

Вернуться в «PHP»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость