Cara Membuat Search Engine dengan PHP dan MySQL

| | | PHP
Cara Membuat Search Engine dengan PHP dan MySQL

fitur pencarian itu hal pertama yang saya tambahkan tiap kali bikin website katalog. kalau datanya baru 20 baris sih enak, tinggal scroll. tapi begitu isinya sudah 500 produk, tanpa search pengunjung pasti nyerah 🙂 saya pernah bikin search untuk toko online kecil, awalnya lambat karena pakai LIKE tanpa index, setelah dirapikan query-nya dan ditambah pagination, hasilnya langsung kerasa cepat.

di artikel ini kita bikin search engine sederhana yang kepakai beneran: form pencarian, proses kata kunci dengan aman, tampilkan hasil pakai highlight, dan bagi ke beberapa halaman. tidak usah pakai library berat, cukup PHP dan MySQL yang sudah ada di XAMPP/Laragon.

1. Siapkan Database dan Tabel

kita butuh satu tabel buat nyimpen data artikel biar ada yang dicari. kalau database belum ada, bikin dulu.

CREATE DATABASE search_engine_db;
USE search_engine_db;

CREATE TABLE artikel (
    id INT AUTO_INCREMENT PRIMARY KEY,
    judul VARCHAR(200) NOT NULL,
    isi TEXT NOT NULL,
    kategori VARCHAR(50) NOT NULL,
    penulis VARCHAR(100) NOT NULL,
    tanggal_post DATE NOT NULL,
    views INT DEFAULT 0
) ENGINE=InnoDB;

-- contoh data 5 baris biar bisa dites
INSERT INTO artikel (judul, isi, kategori, penulis, tanggal_post, views) VALUES
('Cara Install PHP di Windows', 'Panduan install PHP di Windows pakai XAMPP.', 'Tutorial', 'Sigit N', '2026-01-15', 1520),
('Tutorial MySQL untuk Pemula', 'Belajar MySQL dari nol, bikin database dan tabel.', 'Tutorial', 'Sigit N', '2026-01-20', 2340),
('Membuat CRUD dengan PHP dan MySQL', 'Tutorial CRUD dengan PHP dan MySQL plus validasi.', 'Tutorial', 'Sigit N', '2026-02-01', 3100),
('Apa itu REST API?', 'Penjelasan REST API dan format JSON dengan PHP.', 'Konsep', 'Sigit N', '2026-02-10', 1890),
('Cara Deploy Website di Vercel', 'Tutorial deploy website statis di Vercel.', 'Hosting', 'Sigit N', '2026-03-01', 980);

jika data sudah ada di tabel lain, tidak perlu bikin ulang, cukup sesuaikan nama tabel dan kolom di query nanti. untuk pencarian bahasa Indonesia, LIKE sudah cukup, tidak perlu FULLTEXT yang butuh parser English.

2. Koneksi Database yang Aman

bikin file config/database.php biar koneksi terpusat. pakai mysqli dengan exception biar error ketahuan.

<?php
$host = 'localhost';
$dbname = 'search_engine_db';
$username = 'root';
$password = '';

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$conn = new mysqli($host, $username, $password, $dbname);
$conn->set_charset('utf8mb4');

kalau koneksi gagal, mysqli akan lempar exception, jadi tidak diam-diam return false seperti mode default.

3. Buat Form Pencarian

ini form paling sederhana, cuma input dan select kategori. perhatikan method="GET" biar kata kunci kelihatan di URL dan bisa di-bookmark.

<!-- index.php -->
<?php require_once 'config/database.php'; ?>
<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <title>Cari Artikel</title>
</head>
<body>
    <h2>Cari Artikel</h2>
    <form action="hasil.php" method="GET">
        <input type="text" name="q" placeholder="Ketik kata kunci..." required
               value="<?= htmlspecialchars($_GET['q'] ?? '') ?>">
        <select name="kategori">
            <option value="">Semua Kategori</option>
            <option value="Tutorial">Tutorial</option>
            <option value="Konsep">Konsep</option>
            <option value="Hosting">Hosting</option>
        </select>
        <button type="submit">Cari</button>
    </form>

    <p>contoh pencarian populer:
        <a href="hasil.php?q=php+mysql">PHP MySQL</a>
        <a href="hasil.php?q=laravel">Laravel</a>
        <a href="hasil.php?q=rest+api">REST API</a>
    </p>
</body>
</html>

jangan lupa htmlspecialchars di value biar kalau kata kuncinya ada tanda kutip tidak merusak form.

4. Proses Kata Kunci dan Query LIKE dengan Aman

ini bagian paling penting. jangan tempel $_GET['q'] langsung ke query, rawan SQL injection. pakai prepared statement.

<?php
// hasil.php
require_once 'config/database.php';

$q = trim($_GET['q'] ?? '');
$kategori = $_GET['kategori'] ?? '';
$page = max(1, (int)($_GET['page'] ?? 1));
$per_page = 5;

if ($q === '') {
    header('Location: index.php');
    exit;
}

// siapkan kata untuk LIKE
$like = '%' . $q . '%';

// hitung total data
if ($kategori !== '') {
    $stmt = $conn->prepare("SELECT COUNT(*) FROM artikel WHERE (judul LIKE ? OR isi LIKE ?) AND kategori = ?");
    $stmt->bind_param('sss', $like, $like, $kategori);
} else {
    $stmt = $conn->prepare("SELECT COUNT(*) FROM artikel WHERE judul LIKE ? OR isi LIKE ?");
    $stmt->bind_param('ss', $like, $like);
}
$stmt->execute();
$stmt->bind_result($total);
$stmt->fetch();
$stmt->close();

$total_pages = (int)ceil($total / $per_page);
if ($page > $total_pages && $total_pages > 0) $page = $total_pages;
$offset = ($page - 1) * $per_page;

// ambil data halaman ini
if ($kategori !== '') {
    $stmt = $conn->prepare("SELECT id, judul, isi, kategori, penulis FROM artikel WHERE (judul LIKE ? OR isi LIKE ?) AND kategori = ? ORDER BY views DESC LIMIT ? OFFSET ?");
    $stmt->bind_param('sssii', $like, $like, $kategori, $per_page, $offset);
} else {
    $stmt = $conn->prepare("SELECT id, judul, isi, kategori, penulis FROM artikel WHERE judul LIKE ? OR isi LIKE ? ORDER BY views DESC LIMIT ? OFFSET ?");
    $stmt->bind_param('ssii', $like, $like, $per_page, $offset);
}
$stmt->execute();
$hasil = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);

menurut saya, pakai LIKE dengan prepare seperti di atas sudah cukup untuk data di bawah 10 ribu baris. kalau datanya sudah puluhan ribu dan mulai lambat, baru pertimbangkan FULLTEXT atau index di kolom judul.

5. Tampilkan Hasil dengan Highlight dan Pagination

tampilkan hasil dengan aman pakai htmlspecialchars, lalu tandai kata kunci pakai <mark>. pagination jangan lupa bawa q dan kategori di setiap link.

<p>ditemukan <strong><?= $total ?></strong> hasil untuk "<strong><?= htmlspecialchars($q) ?></strong>"</p>

<?php if (empty($hasil)): ?>
    <p>tidak ada hasil, coba kata lain atau perbaiki ejaan.</p>
<?php else: ?>
    <?php foreach ($hasil as $row): ?>
        <div style="border:1px solid #ddd; padding:15px; margin-bottom:12px;">
            <small><?= htmlspecialchars($row['kategori']) ?></small>
            <h3><?= highlight($row['judul'], $q) ?></h3>
            <p><?= highlight(mb_strimwidth($row['isi'], 0, 200, '...'), $q) ?></p>
            <small>penulis: <?= htmlspecialchars($row['penulis']) ?></small>
        </div>
    <?php endforeach; ?>

    <!-- pagination -->
    <?php if ($total_pages > 1): ?>
        <div>
            <?php
            $base = http_build_query(['q' => $q, 'kategori' => $kategori]);
            if ($page > 1) echo '<a href="?'.$base.'&page='.($page-1).'">« Prev</a> ';
            for ($i = 1; $i <= $total_pages; $i++) {
                $cls = $i === $page ? ' style="font-weight:bold;"' : '';
                echo '<a href="?'.$base.'&page='.$i.'"'.$cls.'>'.$i.'</a> ';
            }
            if ($page < $total_pages) echo '<a href="?'.$base.'&page='.($page+1).'">Next »</a>';
            ?>
        </div>
    <?php endif; ?>
<?php endif; ?>

<?php
function highlight($teks, $kata) {
    $kata = preg_quote($kata, '/');
    return preg_replace("/($kata)/i", '<mark>$1</mark>', htmlspecialchars($teks));
}
?>

jika kalian perhatikan, highlight selalu pakai htmlspecialchars dulu baru preg_replace, jadi tag <mark> tetap aman dan tidak kena XSS. ini detail kecil yang sering kelewat di tutorial lain.

Tips Biar Search Tidak Lemot

saya pernah menghabiskan waktu karena search lambat padahal cuma 2 ribu baris, ternyata tidak ada index di kolom judul. tambahkan index biar LIKE 'kata%' (tanpa % di depan) bisa pakai index:

ALTER TABLE artikel ADD INDEX idx_judul (judul);

dan hindari LIKE '%kata' dengan % di depan kalau tidak perlu, karena itu tidak pakai index. untuk kebutuhan sederhana, LIKE '%kata%' plus LIMIT dan pagination seperti di atas sudah cukup.

Kesimpulan

membuat search engine dengan PHP dan MySQL intinya lima langkah: bikin form GET, ambil kata kunci dengan aman, query LIKE pakai prepared statement, tampilkan hasil dengan htmlspecialchars dan highlight, lalu bagi pakai pagination. tidak perlu FULLTEXT di awal, fokus bikin yang aman dan jalan dulu.

fungsi mysqli fetch assoc di php –>

Pertanyaan yang Sering Diajukan

Apa itu search engine sederhana dengan PHP?

Search engine sederhana adalah fitur pencarian yang mencocokkan kata kunci dari form dengan data di database MySQL pakai LIKE atau FULLTEXT, lalu menampilkan hasilnya dengan highlight dan pagination.

Kenapa pakai LIKE bukan FULLTEXT untuk bahasa Indonesia?

LIKE cocok untuk data kecil-menengah dan tidak butuh parser bahasa Inggris. FULLTEXT butuh index khusus dan parser English default, jadi untuk pencarian bahasa Indonesia LIKE lebih gampang dan hasilnya tetap relevan.

Bagaimana mencegah SQL injection di fitur search?

Jangan tempel kata kunci langsung ke query. Pakai prepared statement mysqli_prepare atau PDO prepare dengan bind_param, lalu tampilkan hasil pakai htmlspecialchars biar tidak kena XSS.

Bagaimana pagination di halaman hasil search?

Hitung total baris dengan COUNT, hitung total halaman dengan ceil(total/per_page), lalu ambil data pakai LIMIT dan OFFSET. Bawa kata kunci di setiap link pagination pakai http_build_query.

Sigit Nurhanafi avatar
Full-stack developer & technical writer. Berpengalaman di PHP, Laravel, NodeJS, MySQL, dan Python. Aktif menulis tutorial pemrograman dan maintaining open-source projects di PemburuKode sejak 2021.