За последние 24 часа нас посетили 17090 программистов и 1611 роботов. Сейчас ищут 1123 программиста ...

PHP с открытым кодом HTML

Тема в разделе "PHP для новичков", создана пользователем Булат Азат улы, 29 апр 2023.

  1. Булат Азат улы

    Булат Азат улы Активный пользователь

    С нами с:
    31 авг 2017
    Сообщения:
    61
    Симпатии:
    6
    Адрес:
    Республика Татарстан, город Казань
    Всех приветствую, товарищи!
    Хотел бы вас попросить направить меня "в правильное русло" написания кода PHP. А то у меня код HTML зачастую присваивается к переменным, в итоге - длинная строка с неудобным для восприятия кодом HTML.
    Дело в том, что в основной странице index.php в <body> у меня выводится одна переменная (<?= $mainContent ?>), в <title>, скриптах и стилях - переменная, а наверху страницы подкрепляю доп. страницу PHP в зависимости от адресной строки, в которой и задаются данные для этих переменных.
    И вот хотел бы у вас спросить, как выводить HTML-код удобным для чтения? А то я могу писать красивый код только там, где есть "echo".
    Вот пример, как я это делаю:
    Страница "index.php":
    PHP:
    1. <?php
    2. require_once(__DIR__ ."/config.php");
    3. require_once(__DIR__ ."/routes.php");
    4. /*
    5. ini_set('display_errors',1);
    6. error_reporting(E_ALL);
    7. */
    8. $routePath = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
    9. if ($routes[$routePath] ?? false) {
    10.    require(__DIR__ . '/pages/' . $routes[$routePath]);
    11. } else {
    12.    require(__DIR__ . '/pages/404.php');
    13. }
    14.  
    15. ?>
    16. <!DOCTYPE html>
    17. <html>
    18. <head>
    19.     <meta charset="utf-8">
    20.     <meta name = "viewport" content = "width=device-width, initial-scale=1">
    21.     <title><?= $titleName ?></title>
    22.     <meta name="description" content="<?= $description ?>" />
    23.     <meta name="keywords" content="<?= $keywords ?>">
    24.     <link rel="shortcut icon" href="/images/icon.ico">
    25.     <?= $style ?>
    26.     <script src="/js/jquery.js" type="text/javascript"></script>
    27.     <?= $JS ?>
    28. </head>
    29. <body>
    30.     <?= $mainContent ?>
    31. </body>
    32. </html>
    И, например, вот подключаемая страница (данная страница подключается ещё через одну - но в этой главная информация, и больше отображает масштаб "болезни"):
    PHP:
    1. <?php
    2. $titleName = "Имя Title";
    3. $JS .= "<script src='/js/script1.js' type='text/javascript'></script><script src='/js/script2.js' type='text/javascript'></script>";
    4. $style = "<link href='/css/style1.css' type='text/css' rel='stylesheet'>";
    5.  
    6. $rList = "";
    7. $resRList = $mb->query("SELECT ... выборка из базы...");
    8. $dataRList = $resRList->fetchAll(PDO::FETCH_ASSOC);
    9. foreach($dataRList as $itemRList){
    10.     $rList .= "<tr data-id='".$itemRList['id']."' class='remList'><td>".$itemRList['markaName']." ".$itemRList['modelName']."</td><td>".$itemRList['view']."</td><td>".$itemRList['state']."</td><td>".$itemRList['data']."</td><td>".$itemRList['name']."</td><td><button class='accept'>Принять</button><button class='garantAktPg'>Гарантия</button></td></tr>";
    11. }
    12. $mainContent = "<a class='topBtn leftBtn' href='../'> Назад</a><a id='NewDevice' class='topBtn rightBtn'>➕ Новый аппарат</a><h1>РЕМОНТ</h1><table id='appList' class='topList'><tr><th id='thApparat'>Аппарат</th><th id='thApparatView'>Вид аппарата</th><th id='thState'>Состояние</th><th id='thAcceptDate'>Принят</th><th id='thKlient'>Клиент</th><th>Акты</th></tr>".$rList."</table><div id='popup'><div id='subPopup'><fieldset><legend>Клиент</legend><table><tr><td>Имя клиента:</td><td><input name='klName' type='text' size='30' maxlength='50' placeholder='Имя клиента' list='nKlientList' autocomplete='off'></td></tr><tr><td>Телефон:</td><td><b>+7</b><input name='klTelNom' type='tel' size='27' maxlength='22' placeholder='Телефон клиента' list='nKlientTelNom' autocomplete='off'></td></tr><tr><td>Адрес:</td><td><input name='klAdres' type='text' size='50' maxlength='100' placeholder='Адрес клиента' autocomplete='off'></td></tr><tr><td>Комментарий:</td><td><input name='klComment' type='text' size='50' maxlength='100' placeholder='Комментарий о клиенте' autocomplete='off'></td></tr></table></fieldset><div id='btnDiv'><button id="btnClear" type='button'>Очистить</button><button id="btnSubmit" type='button'>Сохранить</button><button id="btnSubmitPrint" type='button'>Сохранить и Распечатать</button><button id='btnClose'>&#10006;</button></div></div></div>";
    13. ?>
     
  2. rr33rr

    rr33rr Активный пользователь

    С нами с:
    6 май 2021
    Сообщения:
    35
    Симпатии:
    18
    В php строки могут содержать переводы строк. Так что выводите как вам удобно:
    PHP:
    1. $mainContent="
    2. <a class='topBtn leftBtn' href='../'> Назад</a>
    3. <a id='NewDevice' class='topBtn rightBtn'>➕ Новый аппарат</a>
    4. <h1>РЕМОНТ</h1>
    5. <table id='appList' class='topList'>
    6.  <tr>
    7.    <th id='thApparat'>Аппарат</th>
    8. ...";
     
  3. Drunkenmunky

    Drunkenmunky Активный пользователь

    С нами с:
    12 авг 2020
    Сообщения:
    1.484
    Симпатии:
    281
  4. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.839
    Симпатии:
    651
    Перестаньте называть все подряд страницами :) index.php – это фронт-контроллер (единая точка входа), подключаемая в нем «страница» с кодом – контроллер.

    По вашему сабжу см. «вложенные шаблоны». Они часто называются просто шаблонами, а то, что вы воткнули в конец фронта, – общим шаблоном или макетом страниц (их тоже может быть несколько). Вложенные шаблоны могут подключаться из контроллера или фронт-контроллера. Обычно они не прямо втыкаются в макет (хотя макет можно поделить на блоки при помощи include/require), а выполняются заранее и уже результат этой обработки при помощи переменной (прям как у вас: <?= $content ?>) втыкается в макет. Для примера см., как работает фронт G-Drive (он еще и данные по минимуму может подтягивать из БД, так что контроллер не всегда нужно подключать, но не суть): https://gency.ru/g-drive-quick-start
     
  5. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.107
    Симпатии:
    1.243
    Адрес:
    там-сям
    @Булат Азат улы видно что ты учишся, впитываешь советы. Уважаю!

    В твоём "фронт-контроллере" совсем не обязательно подключать "главный шаблон" и потом мучаться а как же его правильно использовать. :) Есть случаи, когда шаблон вообще не нужен. Например при редиректе. Поэтому не надо его здесь.

    Пусть шаблоны подключаются в контроллерах. То есть в файлах, которые ты инклудишь в
    PHP:
    1. require(__DIR__ . '/pages/' . $routes[$routePath]);
    Если тебе надо задать какое-то общее оформление (часто называют layout) это можно сделать в самих шаблонах.
    Пригодится группа функций для работы с буфером вывода, начинающаяся на ob_: https://www.php.net/manual/ru/ref.outcontrol.php

    Напишу для тебя простейшую оболочку для шаблонов.

    index.php
    PHP:
    1. <?php
    2.  
    3. function view(string $template, array $data)
    4. {
    5.   extract($data);
    6.   require __DIR__ . '/templates/' . $template . '.tpl.php';
    7. }
    8.  
    9.  
    10. view('example1', [
    11.   'errors' => [ 'Wrong username or password' ],
    12.   'lines' => [
    13.     'line 1',
    14.     'line 2',
    15.   ],
    16. ]);
    мне не нужен HTML в переменных на этом уровне. пусть он будет ТОЛЬКО в шаблонах.

    "главный шаблон" будет в templates/layout.tpl.php
    PHP:
    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4.   <meta charset="utf-8">
    5.   <meta name = "viewport" content = "width=device-width, initial-scale=1">
    6.   <title><?= $title ?? 'Default title' ?></title>
    7.   <meta name="description" content="<?= $description ?? '' ?>" />
    8.   <meta name="keywords" content="<?= $keywords ?? '' ?>">
    9.   <link rel="shortcut icon" href="/images/icon.ico">
    10.   <style>
    11.   .error { padding: 10px; background-color: #fff0f0; }
    12.   </style>
    13.   <script src="/js/jquery.js" type="text/javascript"></script>
    14. </head>
    15. <body>
    16. <?php if(!empty($errors)): ?>
    17.   <ul class="error">
    18. <?php  foreach($errors as $e): ?>
    19.   <li class="error"><?= $e ?></li>
    20. <?php  endforeach; ?>
    21.   </ul>
    22. <?php endif; ?>
    23.  
    24.   <?= $content ?>
    25. </body>
    26. </html>
    и один из возможных шаблонов максимально простой templates/example1.tpl.php
    PHP:
    1. <?php
    2.  
    3.  
    4. foreach ($lines as $line) {
    5. ?>
    6.  
    7.   <p><?= htmlspecialchars($line); ?></p>
    8.  
    9. <?php
    10. }
    11.  
    12. $content = ob_get_clean();
    13.  
    14. require __DIR__ . '/layout.tpl.php';
     
  6. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.839
    Симпатии:
    651
    @artoodetoo, зачем ф-ции ob_* втыкать прямо в шаблон? Такое редко бывает нужно, когда по сути два разных (и более) шаблона хранят в одном файле (типа один/ob_get_clean/start/два). А ссылку на родительский шаблон/макет можно объявить, но не подключать его явно. Пускай опять «рендер» потрудится.
    --- Добавлено ---
    Что-то вроде этого:
    PHP:
    1. <?php layout('layout2'); ?>
    2. <h1><?= $page['name'] ?></h1>
    3. <?= $page['content'] ?>
    --- Добавлено ---
    При редиректе и т.п. можно использовать пустой макет или сильно упрощенный со ссылкой на цель редиректа.
     
    #6 miketomlin, 30 апр 2023
    Последнее редактирование: 30 апр 2023
  7. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.107
    Симпатии:
    1.243
    Адрес:
    там-сям
    @miketomlin ну это неполноценные шаблоны. Не суди строго ))) Трудно сделать одновременно простой и показательный пример.
    --- Добавлено ---
    пара ob_start - ob_get в "настоящем" шаблонизаторе может быть замаскирована во что-то вроде @section - @endsection и вполне знаешь ли сидит в самом шаблоне.
     
  8. don.bidon

    don.bidon Активный пользователь

    С нами с:
    28 мар 2021
    Сообщения:
    914
    Симпатии:
    143
    Участвовал в разработке CMS, что шустрила на любом хостинге. Времена до AJAX-овые были, кэшировали всё, что можно, потому ob_start() вначале, ob_get.. в конце, весь выхлоп страницы сразу складывался в БД (почему в БД, не надо объяснять исходя из вводных, надеюсь).
     
  9. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.839
    Симпатии:
    651
    От этой фигни избавились не только из-за AJAX'а. Кешировать страницы целиком можно не в движке. У нас (точнее у наших клиентов) куча сайтов, где AJAX используется по минимуму. Там тоже страницы почти всегда кешируются кусками. Целиком кешируются только карты сайтов и т.п.
    --- Добавлено ---
    Хотя специализация – визитки, авторские витрины (нагрузка небольшая). Это, наверное, тоже играет роль.
     
  10. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.839
    Симпатии:
    651
    Можно просто между «секциями» делать что-то вроде save_as('section1'). А последнюю (или единственную) секцию сохранит сам рендер.
     
    artoodetoo нравится это.