Przejdź do treści

Wyszukiwarka na stronie z podświetlaniem wyników

  • Baza danych
  • poziom: średni
  • aktualizacja: 12 lipca 2026

Własna wyszukiwarka na stronie to jeden z najczęściej powtarzających się elementów. Ten skrypt szuka frazy w wybranych kolumnach tabeli, radzi sobie z wieloma słowami (wszystkie muszą wystąpić), poprawnie traktuje znaki specjalne % i _, a znalezioną frazę podświetla w wynikach.

PHP 101 linii Pobierz .php
<?php
/**
 * Wyszukiwarka z podświetlaniem — skryptyPHP.com
 * Zapisz jako: szukaj.php
 * Wymaga tabeli, np. artykuly(id, tytul, tresc) — patrz skrypt „Paginacja".
 */

require 'baza.php'; // skrypt „Połączenie z bazą (PDO)"
$pdo = polacz_z_baza();

$fraza  = trim($_GET['q'] ?? '');
$wyniki = [];
$szukano = false;

if (mb_strlen($fraza) >= 3) {
    $szukano = true;

    // Dzielimy frazę na słowa — każde musi wystąpić w tytule lub treści
    $slowa    = preg_split('~\s+~', $fraza, -1, PREG_SPLIT_NO_EMPTY);
    $warunki  = [];
    $parametry = [];

    foreach ($slowa as $slowo) {
        // W LIKE znaki % i _ mają specjalne znaczenie — maskujemy je
        $bezpieczne = addcslashes($slowo, '%_\\');
        $warunki[]  = '(tytul LIKE ? OR tresc LIKE ?)';
        $parametry[] = '%' . $bezpieczne . '%';
        $parametry[] = '%' . $bezpieczne . '%';
    }

    $sql = 'SELECT id, tytul, tresc
              FROM artykuly
             WHERE ' . implode(' AND ', $warunki) . '
             ORDER BY dodano DESC
             LIMIT 50';

    $stmt = $pdo->prepare($sql);
    $stmt->execute($parametry);
    $wyniki = $stmt->fetchAll();
}

/**
 * Bezpiecznie skraca tekst i podświetla szukane słowa znacznikiem <mark>.
 */
function podswietl(string $tekst, string $fraza, int $limit = 200): string
{
    if (mb_strlen($tekst) > $limit) {
        $tekst = mb_substr($tekst, 0, $limit) . '…';
    }

    // Najpierw zabezpieczamy HTML, dopiero potem dodajemy <mark>
    $bezpieczny = htmlspecialchars($tekst);

    $slowa = preg_split('~\s+~', $fraza, -1, PREG_SPLIT_NO_EMPTY);
    foreach ($slowa as $slowo) {
        $wzorzec = '~' . preg_quote(htmlspecialchars($slowo), '~') . '~iu';
        $bezpieczny = preg_replace($wzorzec, '<mark>$0</mark>', $bezpieczny);
    }
    return $bezpieczny;
}
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Wyszukiwarka</title>
<style>
    body { font-family: sans-serif; max-width: 640px; margin: 20px auto; }
    .szukaj input[type=search] { padding: 8px; width: 70%; }
    .szukaj button { padding: 8px 18px; }
    .wynik { margin: 18px 0; }
    mark { background: #ffe08a; padding: 0 2px; }
</style>
</head>
<body>

<form class="szukaj" method="get" action="">
    <input type="search" name="q" placeholder="Czego szukasz? (min. 3 znaki)"
           value="<?= htmlspecialchars($fraza) ?>" required minlength="3">
    <button type="submit">Szukaj</button>
</form>

<?php if ($szukano): ?>
    <p>Wyników dla „<strong><?= htmlspecialchars($fraza) ?></strong>": <?= count($wyniki) ?></p>

    <?php foreach ($wyniki as $w): ?>
        <div class="wynik">
            <h3><?= podswietl($w['tytul'], $fraza, 120) ?></h3>
            <p><?= podswietl($w['tresc'], $fraza) ?></p>
        </div>
    <?php endforeach; ?>

    <?php if (!$wyniki): ?>
        <p>Nic nie znaleziono. Spróbuj innych słów.</p>
    <?php endif; ?>
<?php elseif ($fraza !== ''): ?>
    <p>Wpisz co najmniej 3 znaki.</p>
<?php endif; ?>

</body>
</html>

Jak użyć tego skryptu

  1. Podłącz plik baza.php i zmień w zapytaniu nazwę tabeli oraz przeszukiwane kolumny na swoje.
  2. Formularz wysyła frazę metodą GET (?q=fraza), dzięki czemu wyniki można podlinkować i cofać się przeglądarką.
  3. Dostosuj limit wyników (LIMIT 50) lub połącz skrypt z gotową paginacją z tej strony.

Warto wiedzieć

  • Fraza trafia do zapytania wyłącznie jako parametr prepare/execute — SQL injection odpada. Dodatkowo maskujemy % i _, żeby użytkownik nie mógł „rozszczelnić" wzorca LIKE.
  • W funkcji podświetlania najpierw wywołujemy htmlspecialchars(), a dopiero potem dodajemy <mark> — kolejność jest kluczowa dla ochrony przed XSS.
  • Przy dużych tabelach LIKE '%...%' nie korzysta z indeksów — rozważ wtedy indeks FULLTEXT i składnię MATCH ... AGAINST.
#wyszukiwarka #like #pdo #mark #xss

Podobne skrypty