1. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

Как распарсить шаблон? (PHP)

Тема в разделе "Оффтопик", создана пользователем W_0rld, 8 июл 2017.

  1. Автор темы
    W_0rld

    W_0rld Активный участник Пользователь

    Баллы:
    61
    Имя в Minecraft:
    World
    Допустим имею такой код:
    PHP:
    $content '<div class="title">%TITLE%</div>
    <div class="block">
    %TEXT%
    </div>'
    ;
    После работы цикла необходимо получить такую переменную:
    PHP:
    $find = array('%TITLE%','%TEXT%');
    $replace = array($row['TITLE'], $row['TEXT']);
    Слова в скобках (процентах) могут быть любые, главное что-бы были в скобках (процентах) - т.е и такое слово %CONTENT%, и такое - %ID%.

    Кому не трудно, покажите пример как такое можно осуществить?
     
  2. Toster_tpl

    Toster_tpl Старожил Пользователь

    Баллы:
    153
    PHP:
    $text strtr($text, [
       
    '%TITLE%' => $row['TITLE'],
       
    '%TEXT%' => $row['TEXT']
    ]);
     
  3. Negezor

    Negezor Активный участник Пользователь

    Баллы:
    78
    PHP сам себе шаблонизатор. Воспринимаю серьёзно только Twig.
     
  4. Автор темы
    W_0rld

    W_0rld Активный участник Пользователь

    Баллы:
    61
    Имя в Minecraft:
    World
    Не, в теории он должен сам через цикл сооружать массив что-бы было универсально.
    Т.Е мы получаем с базы шаблон с ключами, парсим их, потом убираем процентики и используя как название массива уже используем в preg_replace для замены на значение из базы и вывода на страницу.
    PHP:
    <?php
    $object 
    '<div class="title">%TITLE%</div><div class="block">%TEXT%</div>';
    $row = array('TITLE' => 'Привет''TEXT' => 'Это текст');
      foreach (
    $object as $k => $v) { //Код пока не работает
        
    array_push ($find"/%".$k."%/");
        
    array_push ($replace$v);
      }
    exit(
    preg_replace($find$row[$replace], $object));
    ?>
    Создал вопрос на тостере, ибо самому пока мозгов не хватает.
     
  5. Toster_tpl

    Toster_tpl Старожил Пользователь

    Баллы:
    153
    Надо правильно поставить вопрос. Что имеется и что должно быть на выходе. Но если я правильно понял то
    PHP:
    $row = ['TITLE' => 'Привет''TEXT' => 'Это текст'];

    $object '<div class="title">%TITLE%</div><div class="block">%TEXT%</div>';
    $search preg_match_all("/\%([A-Z0-9]+)\%/"$object$matches);

    if(isset(
    $matches[1]) && !empty($matches[1])){
        foreach(
    $matches as $k => $v){
            if(isset(
    $row[$v])){ $object strtr($object"%$v%"$row[$v]); }
        }
    }
     
  6. Автор темы
    W_0rld

    W_0rld Активный участник Пользователь

    Баллы:
    61
    Имя в Minecraft:
    World
    Ваш вариант не пробывал, у меня пока вышло так:
    PHP:
    function get($table$params$template) {
    global 
    $localization;
    $title $localization[strtoupper($table)];
    $rows  sql('SELECT * FROM `'.$table.'` ORDER BY `id` DESC'$params);
    preg_match_all('/{([\w]*?)}/'$template$matches);
    foreach (
    $rows as $row) {
    $find    = array();
    $replace = array();
    foreach (
    $matches[0] as $f)  array_push ($find$f);
    foreach (
    $matches[1] as $r)  array_push ($replace$row[strtolower($r)]);
    $content .= str_replace($find$replace$template);
    }
    if (!
    $content$content str_replace("{ALERT}"$localization[strtoupper($table.'_NOT_FOUND')], getTemplate(1));
    return array(
    'TITLE' => $title'CONTENT' => $content);
    }
    Т.Е если в шаблоне так:
    [​IMG]
    HTML:
    <div class="block">
    <div class="title"><a href="/?post={ID}">{TITLE}</a></div>
    <div class="text">{SHORT}</div>
    </div>
    То после работы функции он делает так:
    HTML:
    <div class="block">
    <div class="title"><a href="/?post='.$row['id'].'">'.$row['title'].'</a></div>
    <div class="text">'.$row['short'].'</div>
    </div>
    Что на выходе выглядит так:
    HTML:
    <div class="block">
    <div class="title"><a href="/?post=1">Привет!</a></div>
    <div class="text">Это короткая новость</div>
    </div>
     
  7. Toster_tpl

    Toster_tpl Старожил Пользователь

    Баллы:
    153
    Не проверял
    PHP:
    <?php
    function get($table$params$template) {
        
    $result = ['TITLE' => $localization[strtoupper($table)], 'CONTENT' => ''];
        
    $rows  sql('SELECT * FROM `'.$table.'` ORDER BY `id` DESC'$params);

        if(
    $rows->num_rows<=0){
            
    $result['CONTENT'] = str_replace("{ALERT}"$localization[strtoupper($table.'_NOT_FOUND')], getTemplate(1));
            return 
    $result;
        }

        while(
    $row $rows->fetch_assoc()){
            foreach(
    $row as $k => $v){

                
    $result['CONTENT'] .= str_replace('{'.mb_strtoupper($k'UTF-8').'}'$v$template);
            }
        }

        return 
    $result;
    }
    ?>
    Сразу предупрежу, все элементы {*} должны быть изначально предопределены, т.е. SELECT * в запросе быть не должно, т.е. во первых, скорость работы снижается, во вторых, поля не определены, что добавляет новый цикл внутрь основного. И всё это, естественно, надо кэшировать.
     
  8. Negezor

    Negezor Активный участник Пользователь

    Баллы:
    78
    1. Ужасно и медленно хранить шаблоны в базе
    2. Так же заметил что ты хранишь сессию в базе, а смысл такого в без кластерного сервера?
    3. В чём проблема определить переменные шаблона вручную?

    Да и вообще в чём проблема сделать так?
    PHP:
    $replace = [
      
    '{TITLE}' => 'My title',
      
    '{SHORT}' => 'Short story'
    ];

    $content str_replace(
      
    array_keys($replace),
      
    $replace,
      
    $content
    );
     
  9. Автор темы
    W_0rld

    W_0rld Активный участник Пользователь

    Баллы:
    61
    Имя в Minecraft:
    World
    1. Насколько медленно? Во первых - я люблю эксперементировать, во вторых это для меня удобнее, в третьих у меня не огромный сайт и там не будет 100+ шаблонов.
    2. Опять же повторюсь - у меня простенький сайт и сессии там хранятся только от авторизации с ВК, т.е записывается имя, и response_key. ВСЁ.
    3. Устал от 500+ строк кода (всегда стараюсь использовать функции и сократить время записи кода).
    + данная функция работает только в нескольких страницах, ибо остальные страницы уже работают по "ручному" коду.
    PHP:
    switch ($_GET['sheet']) {
    case 
    'publications':
    if (!isset(
    $_GET['post'])) {
    $publications get('Publications'falsegetTemplate(7));
    $title $publications['TITLE'];
    $content $publications['CONTENT'];
    } else if (
    is_numeric($_GET['post'])) {
    $publication get('Publications', array($_GET['post']), getTemplate(8));
    $title $publication['TITLE'];
    $content $publication['CONTENT'];
    }
    break;

    case 
    'reviews':
    $title   $localization['REVIEWS'];
    $content getTemplate(15);
    break;

    case 
    'audios':
    $title $localization['AUDIOS'];
    $rows sql("SELECT * FROM `Audios` ORDER BY `id` DESC"false);
    foreach (
    $rows as $row) {
    $tbody .= '
    <tr id="'
    .$row['id'].'" title="'.$row['author'].' — '.$row['title'].'" class="truck">
    <td>'
    .$row['author'].'</td>
    <td>'
    .$row['title'].'</td>
    </tr>'
    ;
    }
    $content str_replace("{TBODY}"$tbodygetTemplate(14));
    break;

    case 
    'dev':
    $title $localization['DEV'];
    $content getTemplate(18);
    break;
    }
    За функцию array_keys, спасибо, удобно.
    Спасибо за функцию, коротко и понятно. SELECT * использую опять же для универсальности, таблицы маленькие да и страницы кэшируются, поэтому за скорость не беспокоюсь.
     
  10. Negezor

    Negezor Активный участник Пользователь

    Баллы:
    78
    Аргумент для того что бы не использовать базу)
    Мне показалось там хранятся сессии PHP $_SESSION
    Немного ООП упростило бы код как по мне, а так же использовать запись как констант не очень.
    TITLE ну не очень.
     
  11. Автор темы
    W_0rld

    W_0rld Активный участник Пользователь

    Баллы:
    61
    Имя в Minecraft:
    World
    Сессии PHP это же тоже самое что и куки, просто php сверяет их не из базы.
    У меня просто стоит проверка если кука token есть в базе то юзер авторизован.
    (там ещё его uid и имя берется из той же таблицы, короче говоря Sessions это все равно что Users)
     
  12. Negezor

    Negezor Активный участник Пользователь

    Баллы:
    78
    ... ты точно не знаешь как работают сессии. В обычной практики PHP хранит идентификатор сессии в куках, а потом вытаскивает её из файлов по идентификатору. Есть возможность заменить хранилище скажем на Redis (чем я постоянно пользуюсь) или можно запилить в базу. Я может и ошибся о том что у тебя в MySQL Sessions хранятся сессии PHP.
     
  13. Toster_tpl

    Toster_tpl Старожил Пользователь

    Баллы:
    153
    Шаблоны хранить в базе не медленно, медленно с ними взаимодействовать напрямую с базой, по этому я и упомянул про кэш. Для кэша можно использовать обычный файл, Redis(если с оперативой проблем нет) или же мемкеш. В качестве главного хранилища использовать Redis нельзя, если только сайт не требует такие элементы как поиск, сортировка и т.д. а для кэша самое оно.
     
  14. Автор темы
    W_0rld

    W_0rld Активный участник Пользователь

    Баллы:
    61
    Имя в Minecraft:
    World
    Допилил функцию, вроде все как надо, поддерживает два режима - один вывод шаблонов в виде блоков, другой вставка тела таблицы в шаблон и вывод.
    PHP:
    function get($table$params$template) {
    global 
    $localization;
    global 
    $tables;
    $result = ['TITLE' => $localization[strtoupper($table)], 'CONTENT' => ''];
    $rows  sql('SELECT * FROM `'.$table.'` ORDER BY `id` DESC'$params);
    if (
    $rows->rowCount() > 0)
    {
    $tbody strpos($template'{TBODY}');
    if (
    $tbody)
    {
    foreach(
    $rows->fetchAll(PDO::FETCH_ASSOC) as $row) {
    $tbody .= str_replace(array_map(function($value){ return '{'.mb_strtoupper($value).'}'; }, array_keys($row)), array_values($row), $tables[strtoupper($table)]);
    }
    $result['CONTENT'] = str_replace('{TBODY}'$tbody$template);
    }
    else {
    foreach(
    $rows->fetchAll(PDO::FETCH_ASSOC) as $row) {
    $result['CONTENT'] .= str_replace(array_map(function($value){ return '{'.mb_strtoupper($value).'}'; }, array_keys($row)), array_values($row), $template);
    }
    }
    }
    else 
    $content str_replace("{ALERT}"$localization[mb_strtoupper($table).'_NOT_FOUND'], getTemplate(1));
    return 
    $result;
    }
    Заметил странное поведение, может баг PHP?
    В результате первой работы цикла прибавляются непонятные цифры в начале шаблона О_0
    http://hr-dev.ru/?sheet=audios
    [​IMG]
     
  15. Negezor

    Negezor Активный участник Пользователь

    Баллы:
    78
    Судя по сайту Lumen подошёл бы идеально, а такой AJAX ужасен, хоть JSON Schema сделай и придерживайся её.
     
  16. Автор темы
    W_0rld

    W_0rld Активный участник Пользователь

    Баллы:
    61
    Имя в Minecraft:
    World
    Объясните в чем плюсы использования данного фреймворка? Разве не легче и понятнее писать самому?
     
  17. Negezor

    Negezor Активный участник Пользователь

    Баллы:
    78
    В таком случае дальнейшая поддержка кода будет просто адские мучения, когда подтянешь навыки поймёшь. У тебя не имеется какой то базовой структуры, никакого REST. Представь зайдёшь такой через месяц в код, а что за функция "get" ("получить"), а что получить? С роутингом на switch'ах реализовать SEO URL костылями глупо. Я уже даже не говорю про обработку ошибок, смотри 2 абстрактных примера для красивых URL:
    Твой набросок движка
    Код:
    RewriteRule ^users/([0-9]+)(/?)$ index.php?sheet=users&id=$1&view=profile[L]
    RewriteRule ^users/([0-9]+)/settings(/?)$ index.php?sheet=users&id=$1&view=settings [L]
    
    PHP:
    switch ($_GET['sheet']) {
      case 
    'users':
        
    $id = (int)$_GET['id'];

        if ((
    $_GET['view'] ?? null) === 'settings') {
          
    // Show settings
        
    } else {
          
    // Show profile
        
    }

        break;
    }
    Lumen
    PHP:
    $app->get('/users/{id}', function($id){
      
    // url: /users/:id
    });
    $app->get('/users/{id}/settings', function($id){
      
    // url: /users/:id/settings
    });
    Или как я люблю в Node.js разветвлять middleware на составляющие компонетов:
    Код:
    /* router/users.js */
    import Router from 'koa-router';
    
    const router = new Router;
    
    router.get('/', (context, next) => {
      // url: /users/
    });
    
    $router.get('/:id', (context, next) => {
      // url: /users/:id/
    });
    
    $router.get('/:id/settings', (context, next) => {
      // url: /users/:id/settings
    });
    
    export default router;
    
    /* router/index.js */
    import users from './users';
    // ...
    router.use('/users', ...users);
    
    1. Никаких глобальных переменных
    2. Не нужен apache модуль rewrite
    3. Easy RESTfull API
    4. Легко поддерживаемый код
     
  18. Автор темы
    W_0rld

    W_0rld Активный участник Пользователь

    Баллы:
    61
    Имя в Minecraft:
    World
    Кстати говоря, думал начать изучение Node.JS, там интересно есть все те функции что в PHP?
    Т.Е я смогу там тот-же движок написать?
    И вообще как он работает, тоже типа как модуль к nginx? (люблю только nginx)

    Просто как я понял с первого взгляда он используется в основной для сетевых игр, чатов и т.п
     
  19. Toster_tpl

    Toster_tpl Старожил Пользователь

    Баллы:
    153
    Там нет функций php, там есть функции javascript. По сути Node.js это софт, чем-то напоминающий компилятор, а в качестве основного языка используется javascript + собственные функции ноды. Никаких nginx'ов он не требует.
    Да, движок на нем можно написать.
    При этом хочу заметить, что он работает не синхронно, как php, а асинхронно, что требует необходимых доп. проверок. Если их не производить, то сервер может просто лечь.
     
  20. Автор темы
    W_0rld

    W_0rld Активный участник Пользователь

    Баллы:
    61
    Имя в Minecraft:
    World
    Т.Е я могу заставить его прослушивать порт 80 и заставить послать браузеру допустим <b>Hello World</b> и он будет восприниматься как HTML? Там же ещё headerов куча по идее должна посылаться.
     

Поделиться этой страницей