Всех приветствую, товарищи! Хотел бы вас попросить направить меня "в правильное русло" написания кода PHP. А то у меня код HTML зачастую присваивается к переменным, в итоге - длинная строка с неудобным для восприятия кодом HTML. Дело в том, что в основной странице index.php в <body> у меня выводится одна переменная (<?= $mainContent ?>), в <title>, скриптах и стилях - переменная, а наверху страницы подкрепляю доп. страницу PHP в зависимости от адресной строки, в которой и задаются данные для этих переменных. И вот хотел бы у вас спросить, как выводить HTML-код удобным для чтения? А то я могу писать красивый код только там, где есть "echo". Вот пример, как я это делаю: Страница "index.php": PHP: <?php require_once(__DIR__ ."/config.php"); require_once(__DIR__ ."/routes.php"); /* ini_set('display_errors',1); error_reporting(E_ALL); */ $routePath = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH); if ($routes[$routePath] ?? false) { require(__DIR__ . '/pages/' . $routes[$routePath]); } else { require(__DIR__ . '/pages/404.php'); } ?> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name = "viewport" content = "width=device-width, initial-scale=1"> <title><?= $titleName ?></title> <meta name="description" content="<?= $description ?>" /> <meta name="keywords" content="<?= $keywords ?>"> <link rel="shortcut icon" href="/images/icon.ico"> <?= $style ?> <script src="/js/jquery.js" type="text/javascript"></script> <?= $JS ?> </head> <body> <?= $mainContent ?> </body> </html> И, например, вот подключаемая страница (данная страница подключается ещё через одну - но в этой главная информация, и больше отображает масштаб "болезни"): PHP: <?php $titleName = "Имя Title"; $JS .= "<script src='/js/script1.js' type='text/javascript'></script><script src='/js/script2.js' type='text/javascript'></script>"; $style = "<link href='/css/style1.css' type='text/css' rel='stylesheet'>"; $rList = ""; $resRList = $mb->query("SELECT ... выборка из базы..."); $dataRList = $resRList->fetchAll(PDO::FETCH_ASSOC); foreach($dataRList as $itemRList){ $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>"; } $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'>✖</button></div></div></div>"; ?>
В php строки могут содержать переводы строк. Так что выводите как вам удобно: PHP: $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> ...";
Перестаньте называть все подряд страницами index.php – это фронт-контроллер (единая точка входа), подключаемая в нем «страница» с кодом – контроллер. По вашему сабжу см. «вложенные шаблоны». Они часто называются просто шаблонами, а то, что вы воткнули в конец фронта, – общим шаблоном или макетом страниц (их тоже может быть несколько). Вложенные шаблоны могут подключаться из контроллера или фронт-контроллера. Обычно они не прямо втыкаются в макет (хотя макет можно поделить на блоки при помощи include/require), а выполняются заранее и уже результат этой обработки при помощи переменной (прям как у вас: <?= $content ?>) втыкается в макет. Для примера см., как работает фронт G-Drive (он еще и данные по минимуму может подтягивать из БД, так что контроллер не всегда нужно подключать, но не суть): https://gency.ru/g-drive-quick-start
@Булат Азат улы видно что ты учишся, впитываешь советы. Уважаю! В твоём "фронт-контроллере" совсем не обязательно подключать "главный шаблон" и потом мучаться а как же его правильно использовать. Есть случаи, когда шаблон вообще не нужен. Например при редиректе. Поэтому не надо его здесь. Пусть шаблоны подключаются в контроллерах. То есть в файлах, которые ты инклудишь в PHP: require(__DIR__ . '/pages/' . $routes[$routePath]); Если тебе надо задать какое-то общее оформление (часто называют layout) это можно сделать в самих шаблонах. Пригодится группа функций для работы с буфером вывода, начинающаяся на ob_: https://www.php.net/manual/ru/ref.outcontrol.php Напишу для тебя простейшую оболочку для шаблонов. index.php PHP: <?php function view(string $template, array $data) { extract($data); require __DIR__ . '/templates/' . $template . '.tpl.php'; } view('example1', [ 'errors' => [ 'Wrong username or password' ], 'lines' => [ 'line 1', 'line 2', ], ]); мне не нужен HTML в переменных на этом уровне. пусть он будет ТОЛЬКО в шаблонах. "главный шаблон" будет в templates/layout.tpl.php PHP: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name = "viewport" content = "width=device-width, initial-scale=1"> <title><?= $title ?? 'Default title' ?></title> <meta name="description" content="<?= $description ?? '' ?>" /> <meta name="keywords" content="<?= $keywords ?? '' ?>"> <link rel="shortcut icon" href="/images/icon.ico"> <style> .error { padding: 10px; background-color: #fff0f0; } </style> <script src="/js/jquery.js" type="text/javascript"></script> </head> <body> <?php if(!empty($errors)): ?> <ul class="error"> <?php foreach($errors as $e): ?> <li class="error"><?= $e ?></li> <?php endforeach; ?> </ul> <?php endif; ?> <?= $content ?> </body> </html> и один из возможных шаблонов максимально простой templates/example1.tpl.php PHP: <?php ob_start(); foreach ($lines as $line) { ?> <p><?= htmlspecialchars($line); ?></p> <?php } $content = ob_get_clean(); require __DIR__ . '/layout.tpl.php';
@artoodetoo, зачем ф-ции ob_* втыкать прямо в шаблон? Такое редко бывает нужно, когда по сути два разных (и более) шаблона хранят в одном файле (типа один/ob_get_clean/start/два). А ссылку на родительский шаблон/макет можно объявить, но не подключать его явно. Пускай опять «рендер» потрудится. --- Добавлено --- Что-то вроде этого: PHP: <?php layout('layout2'); ?> <h1><?= $page['name'] ?></h1> <?= $page['content'] ?> --- Добавлено --- При редиректе и т.п. можно использовать пустой макет или сильно упрощенный со ссылкой на цель редиректа.
@miketomlin ну это неполноценные шаблоны. Не суди строго ))) Трудно сделать одновременно простой и показательный пример. --- Добавлено --- пара ob_start - ob_get в "настоящем" шаблонизаторе может быть замаскирована во что-то вроде @section - @endsection и вполне знаешь ли сидит в самом шаблоне.
Участвовал в разработке CMS, что шустрила на любом хостинге. Времена до AJAX-овые были, кэшировали всё, что можно, потому ob_start() вначале, ob_get.. в конце, весь выхлоп страницы сразу складывался в БД (почему в БД, не надо объяснять исходя из вводных, надеюсь).
От этой фигни избавились не только из-за AJAX'а. Кешировать страницы целиком можно не в движке. У нас (точнее у наших клиентов) куча сайтов, где AJAX используется по минимуму. Там тоже страницы почти всегда кешируются кусками. Целиком кешируются только карты сайтов и т.п. --- Добавлено --- Хотя специализация – визитки, авторские витрины (нагрузка небольшая). Это, наверное, тоже играет роль.
Можно просто между «секциями» делать что-то вроде save_as('section1'). А последнюю (или единственную) секцию сохранит сам рендер.