Способ генерации HTML кода на PHP

244
04 мая 2018, 11:44

Меня интересует, насколько правильно я генерирую динамику на сайте.
Допустим, есть основной шаблон (статика) и для генерации контента используется PHP, который в зависимости от условий генерирует HTML и "подставляет" верстку в шаблон:

<html>
 <head>
 ...
 </head>
 <body>
  <div id="row-1">
    <h1>Заголовок</h1>
  </div>
  <div id="row-2">
   <?php content($_SESSION['id']); ?>
  </div>
 </body>
</html>

В этом примере в месте, где нужна динамика, вызывается функция с аргументом id пользователя, который хранится в сессионной переменной:

<?php
 session_start();
 function content($id)
 {
     if(!empty($id))
     {
         $query = mysqli_query(connect(), "SELECT * FROM Post WHERE user_id = $id");
         while($row = mysqli_fetch_assoc($query)
         {
             echo "<div>Пост $row[name]</div><br><p>$row[text]</p>";
         }
     }
     else
     {
         echo "<div>Для просмотра необходимо авторизоваться</div>";
     }
 }

Является ли такой способ генерации верстки приемлемым?
На разных ресурсах по этому вопросу дают противоречивые ответы, вроде, что генерация на стороне сервера требует много трафика или же наоборот, что это верный способ.
Помогите разобраться или подсказать более лучшее решение. Заранее спасибо!
P.S. Я знаю про паттерны (например MVC) и фреймворки с ними связанные, но меня на данный момент интересуют способы написания грамотного кода "своими руками".

Answer 1

Нареканий слишком много, попробуем разобраться.
Про ООП говорить не буду, но классы позволяют гораздо лучше организовать структуру проектов, чем простые глобальные функции.

  • Не нужно вызывать echo без необходимости

Просто замените echo на return, и перенесите его в шаблон:

<?=content($_SESSION['id'])?>
  • Нужно отделять данные от представления

Вынесите получение данных о пользователе в отдельную функцию:

function content($id) {
  $user = getUser(intval($id));
  if (empty($user)) return '...';
  return '...';
}
  • Ведите разработку с максимально высоким уровнем вывода ошибок: error_reporting(-1);
    Так, вы бы увидели, что конструкции вида "$a[some]" генерируют лишние логи, потому как пытаются сначала обнаружить константу some, и только потом полагают, что это строка Assume some as 'some'. Обращения к жесткому диску для логирования могут существенно снизить производительность.

  • Сделайте простой класс для генерации шаблонов
    Рано или поздно, html-код в функции template станент неуправляемым.
    Лучше вынести отображение данных о пользователе в отдельный шаблон. Класс для реализации подобного шаблона пишется элементарно с использованием фунции extract.

Пример такого шаблона:

class Template {
  private $tpl;
  public function __construct($tpl) {$this->tpl = $tpl;}
  // можно добавлять функции-helpers, доступные в темплейте через $this
  public function e($str) {return htmlspecialchars($str);}
  public function render($modelData) {
    try {
      // Делаем переменные доступными в шаблоне
      extract($modelData); // Можно также реализовать какой-нибудь \ArrayAccess и использовать тут $this->data
      ob_start();
      include $this->tpl;
    } catch (\Exception $e) { // Файл не найден, и т.п.
      ob_end_clean();
      throw $e;
    }
    return ob_get_clean();    
  }
}
// Usage:
// user.tpl
<div>
  <?php if (empty($user)): ?>
    <div>Для просмотра необходимо авторизоваться</div>
  <?php else:?>
    <div>Пост <?=$this->e($user['name'])?></div><br>
    <p><?=$this->e($user['text'])?></p>
  <?php endif?>
</div>
// controller
$tpl =  new Template(__DIR__.'/templates/layout.tpl');
$userTpl = new Template(__DIR__.'/templates/user.tpl');
echo $tpl->render([
 'userBlock' => $userTpl->render(['user' => $this->userProvider->find($id)])
]);
Answer 2

Советую вам глянуть в сторону шаблонизаторов, вы можете реализовать всю логику сами, так например использовать паттерн HMVC, но сам вывод динамических данных реализовать по средствам PHP/JS Шаблонизаторов. Из PHP Шаблонизаторов отмечу как самый простой на мой взгляд это Twig, с JS ситуация сложнее, так как в целом в JS Нет такого понятия как «шаблонизатор», просто у фреймворков на JS Есть своя удобная реализация работы с DOM, которая легко позволяет нам выводить динамические данные на страницу.

Answer 3
  1. Не стоит использовать HTML код в PHP. Лучше сделать SQL-select и вернуть массив и сделать это в самом верху к примеру:

    $content = content($_SESSION['id']);
    if($content['code'] !== 200) {
        $error['code'] = 403;
        $error['message'] = 'Необходимо авторизоваться.';
    }

Тогда твоя функция content(); может выглядеть вот так.

function content($id) {
    if(!empty($id)) {
      $query = mysqli_query(connect(), "SELECT * FROM Post WHERE user_id = $id");
      return ['code'=>200, 'posts'=>mysqli_fetch_assoc($query)];
    } else {
      return ['code'=>403, 'message'=> 'Unauthorized']
    }
}

А в html шаблоне уже использовать Альтернативный Синтаксис Управляющих Структур и выводить.

<div class = "posts"> 
<? foreach($content['posts'] as $post): ?> 
  <div class = "post"> 
    <div> 
      <?=$post['name'];?> 
    </div> 
    <br /> 
    <div> 
      <?=$post['text'];?> 
    </div> 
  </div> 
<? endforeach; ?> 
</div>

READ ALSO
PHP, права доступа, работа с файлами

PHP, права доступа, работа с файлами

Есть ситуация, когда на сетевом диске есть несколько каталогов с разными правами доступа для разных пользователей доменаИ в эти каталоги...

188
Антимат на php?

Антимат на php?

Если в строке $str есть матное слово, то $str = "censored";Возможно, с помощью preg_replace?

207
Вызов python-скрипта в PHP

Вызов python-скрипта в PHP

Перечитал все, что доступно на эту тему здесь и на других ресурсах, но проблема упорно не хочет решатьсяЯ пытаюсь вызвать Python скрипт из PHP, перепробовал...

210
PDO подготовленный запрос с IN()

PDO подготовленный запрос с IN()

При переходе на PDO, уперся в очередную "засаду"

205