anlamadığın nokta şu bu tarz köklü scriptlerde her dosyaya functions, config request, gibi dosyalar import edilir sayfalar basit de olsa her sayfa tek bi çatı altından yönetilir
title da buna dahil. çoğu framework backendde daha kullanıcıya çıktı vermeden zaten output escape yapmış oluyor. yani olay orda yazdığım title kodu değil " $pageTitle " ın içi.
atıyorum search.php içine config.php import ettin config.php içerisinde her sayfada titleın nasıl gözükeceğini önceden belirtiyorsun.
title gibi her sayfada değişkenlik gösteren veriler tek bir dosyadan yönetilir, bu dosya her sayfaya import edilir.
kullanıcının yazdığı veri daha tarayıcıya çıktı olarak basılmadan önce backendde php escape olur.
ondan sonra sen çıktı olarak ekranda görürsün.
o yüzden search.php içerisine htmlspecialchars girmişsin girmemişsin fark etmiyor.
bunu neye dayanarak söylüyorum? konudaki ekran görüntüsünde kod html olarak çalışmamış düz string metin olarak ekrana yazdırılmış. bu da demek oluyor ki bu çıktı backendde php escape yapılmış. örneğin (</title><script>alert('123')</script>

.
(php escapeler tarayıcıda ve htmlde düz metin olarak çalışır. aynı ekran görüntüsünde gözüktüğü gibi.)
bahsettiğim senaryoda config.php içeriği;
function escape_output($string)
{
$string = preg_replace('/[\x00-\x1F\x7F]/u', '', $string);
$string = htmlentities($string, ENT_QUOTES | ENT_HTML5, 'UTF-8');
return $string;
}
function set_title($title)
{
global $pageTitle;
$pageTitle = escape_output($title);
}
function render_title()
{
global $pageTitle;
echo "<title>{$pageTitle}</title>"; ("muhtemelen backendde kod <title> <?php echo $pageTitle ?> </title> şeklinde çalışıyor" ) DİYE BAHSETTİĞİM YER BURASI
}
buda kullanıcının gördüğün sayfa yani search.php
<?php
require_once "config.php";
$q = $_GET['q'] ?? '';
set_title("Sorgu için arama sonuçları: " . $q . ");
?>
yani gerçekten helal olsun bana mala anlatır gibi anlattırdın chatgpt işini azaltalım lütfen.