Filter & Validation

Filter & Validation #

Setiap data yang masuk ke aplikasi PHP dari luar — form HTML, query string URL, header HTTP, cookie, JSON dari API — tidak bisa dipercaya begitu saja. PHP menyediakan ekstensi filter yang sering diabaikan padahal sangat powerful: filter_var() dan filter_input() dengan puluhan filter bawaan untuk validasi (apakah nilai valid?) dan sanitasi (bersihkan nilai agar aman). Menggunakan fungsi filter bawaan PHP lebih baik dari menulis validasi manual karena mereka sudah diuji secara ekstensif, menangani edge case yang tidak terduga, dan mengikuti standar RFC yang benar. Artikel ini membahas semua filter penting beserta cara menggunakannya dengan benar — termasuk jebakan yang sering membuat developer mengira data sudah aman padahal belum.

Dua Fungsi Utama #

flowchart LR
    A[Input Eksternal] --> B{Sumber input?}
    B -- "Variabel PHP\n(bisa dari mana saja)" --> C["filter_var(\$nilai, FILTER)"]
    B -- "Superglobal\n$_GET/$_POST/$_COOKIE/dll." --> D["filter_input(INPUT_*, 'nama', FILTER)"]
    C --> E{Valid?}
    D --> E
    E -- Ya --> F[Gunakan nilai]
    E -- Tidak --> G[Tolak / Default]

    style C fill:#dcfce7
    style D fill:#dcfce7
    style G fill:#fee2e2
<?php
// filter_var() — filter nilai PHP yang sudah ada di variabel
$email  = "[email protected]";
$valid  = filter_var($email, FILTER_VALIDATE_EMAIL);
// return nilai asli jika valid, false jika tidak

// filter_input() — ambil DAN filter dari superglobal sekaligus
// Lebih aman karena tidak pernah menyentuh $_GET/$_POST langsung
$email  = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
$halaman = filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT);
$token  = filter_input(INPUT_COOKIE, 'token', FILTER_SANITIZE_ENCODED);

// Konstanta INPUT_*
// INPUT_GET     → $_GET
// INPUT_POST    → $_POST
// INPUT_COOKIE  → $_COOKIE
// INPUT_SERVER  → $_SERVER
// INPUT_ENV     → $_ENV

FILTER_VALIDATE_* — Validasi #

Filter validasi mengembalikan nilai asli jika valid, atau false jika tidak valid. Selalu gunakan === false untuk mengecek kegagalan validasi.

Email #

<?php
// FILTER_VALIDATE_EMAIL
$valid   = filter_var("[email protected]", FILTER_VALIDATE_EMAIL);
// "[email protected]" — valid, mengembalikan nilai aslinya

$invalid = filter_var("bukan-email", FILTER_VALIDATE_EMAIL);
// false

$invalid2 = filter_var("@example.com", FILTER_VALIDATE_EMAIL);
// false

// Contoh penggunaan yang benar
$emailInput = $_POST['email'] ?? '';
$email      = filter_var(trim($emailInput), FILTER_VALIDATE_EMAIL);

if ($email === false) {
    $errors['email'] = "Format email tidak valid";
} else {
    // $email sudah tervalidasi, aman digunakan
    simpanEmail($email);
}

// PERHATIAN: filter_var email TIDAK memverifikasi domain exists
// Untuk verifikasi domain, tambahkan checkdnsrr():
function validasiEmailLengkap(string $email): bool
{
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        return false;
    }
    $domain = substr($email, strrpos($email, '@') + 1);
    return checkdnsrr($domain, 'MX') || checkdnsrr($domain, 'A');
}

URL #

<?php
// FILTER_VALIDATE_URL
$valid   = filter_var("https://example.com", FILTER_VALIDATE_URL);
// "https://example.com"

$valid2  = filter_var("ftp://files.example.com/data.zip", FILTER_VALIDATE_URL);
// valid — semua scheme diterima secara default

$invalid = filter_var("bukan url", FILTER_VALIDATE_URL);
// false

// Dengan flag untuk memfilter scheme yang diizinkan
$options = [
    'flags' => FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED,
];

// Hanya izinkan http dan https
function validasiUrlHttp(string $url): bool
{
    if (!filter_var($url, FILTER_VALIDATE_URL)) {
        return false;
    }
    $scheme = parse_url($url, PHP_URL_SCHEME);
    return in_array($scheme, ['http', 'https'], strict: true);
}

var_dump(validasiUrlHttp("https://example.com")); // true
var_dump(validasiUrlHttp("ftp://example.com"));   // false
var_dump(validasiUrlHttp("javascript:alert(1)")); // false — cegah XSS via URL

// PENTING: filter_var URL tidak berarti URL aman untuk di-redirect!
// Selalu validasi scheme secara eksplisit sebelum header('Location: ...')

Integer dan Float #

<?php
// FILTER_VALIDATE_INT
$valid   = filter_var("42", FILTER_VALIDATE_INT);    // int(42)
$valid2  = filter_var("-10", FILTER_VALIDATE_INT);   // int(-10)
$invalid = filter_var("3.14", FILTER_VALIDATE_INT);  // false
$invalid2 = filter_var("abc", FILTER_VALIDATE_INT);  // false

// Dengan rentang min/max
$options = [
    'options' => [
        'min_range' => 1,
        'max_range' => 100,
    ],
];

$halaman = filter_var("50", FILTER_VALIDATE_INT, $options); // int(50)
$invalid = filter_var("150", FILTER_VALIDATE_INT, $options); // false — melebihi 100
$invalid2 = filter_var("0", FILTER_VALIDATE_INT, $options);  // false — di bawah 1

// Penggunaan praktis: parameter pagination
$halaman = filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT, [
    'options' => ['min_range' => 1, 'default' => 1],
]);
$halaman = $halaman ?: 1; // gunakan default 1 jika null atau false

// FILTER_VALIDATE_FLOAT
$valid   = filter_var("3.14", FILTER_VALIDATE_FLOAT);    // float(3.14)
$valid2  = filter_var("1.5e3", FILTER_VALIDATE_FLOAT);   // float(1500)
$valid3  = filter_var("1,500.75", FILTER_VALIDATE_FLOAT, [
    'flags' => FILTER_FLAG_ALLOW_THOUSAND, // izinkan koma sebagai pemisah ribuan
]);

// Dengan desimal koma (format Eropa/Indonesia)
$options = ['options' => ['decimal' => ',']]; // koma sebagai desimal
$valid4  = filter_var("1.500,75", FILTER_VALIDATE_FLOAT, $options); // 1500.75

Boolean #

<?php
// FILTER_VALIDATE_BOOLEAN — lebih cerdas dari (bool)$nilai
// Mengembalikan true, false, atau null (jika nilai ambigu)

// Nilai yang dianggap TRUE:
// "true", "on", "yes", "1", 1, true (case-insensitive)
var_dump(filter_var("true",  FILTER_VALIDATE_BOOLEAN)); // bool(true)
var_dump(filter_var("yes",   FILTER_VALIDATE_BOOLEAN)); // bool(true)
var_dump(filter_var("on",    FILTER_VALIDATE_BOOLEAN)); // bool(true)
var_dump(filter_var("1",     FILTER_VALIDATE_BOOLEAN)); // bool(true)
var_dump(filter_var(true,    FILTER_VALIDATE_BOOLEAN)); // bool(true)

// Nilai yang dianggap FALSE:
// "false", "off", "no", "0", 0, false (case-insensitive)
var_dump(filter_var("false", FILTER_VALIDATE_BOOLEAN)); // bool(false)
var_dump(filter_var("no",    FILTER_VALIDATE_BOOLEAN)); // bool(false)
var_dump(filter_var("0",     FILTER_VALIDATE_BOOLEAN)); // bool(false)

// Nilai AMBIGU mengembalikan null (bukan false!)
var_dump(filter_var("maybe", FILTER_VALIDATE_BOOLEAN)); // NULL
var_dump(filter_var("",      FILTER_VALIDATE_BOOLEAN)); // NULL

// Dengan FILTER_NULL_ON_FAILURE — null untuk ambigu, false hanya untuk false
$result = filter_var("invalid", FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
// NULL — ambigu

// Berguna untuk konfigurasi dari env variable
$debug = filter_var(getenv('APP_DEBUG'), FILTER_VALIDATE_BOOLEAN);
// getenv mengembalikan string — filter_var mengkonversinya ke boolean yang benar

IP Address #

<?php
// FILTER_VALIDATE_IP
$valid   = filter_var("192.168.1.1", FILTER_VALIDATE_IP);    // "192.168.1.1"
$valid2  = filter_var("::1", FILTER_VALIDATE_IP);            // "::1" (IPv6)
$invalid = filter_var("999.999.999.999", FILTER_VALIDATE_IP); // false

// Flag untuk filter lebih spesifik
// Hanya IPv4
$ipv4 = filter_var("192.168.1.1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
// Hanya IPv6
$ipv6 = filter_var("::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);

// Tolak IP privat (192.168.x.x, 10.x.x.x, 172.16-31.x.x)
$publik = filter_var("192.168.1.1", FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE);
// false — karena 192.168.x.x adalah privat

// Tolak IP reserved (loopback 127.x.x.x, dll.)
$publik2 = filter_var("127.0.0.1", FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE);
// false

// Validasi IP client yang nyata (di balik proxy/load balancer)
function getClientIp(): ?string
{
    $headers = ['HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP', 'REMOTE_ADDR'];

    foreach ($headers as $header) {
        if (!empty($_SERVER[$header])) {
            $ip = trim(explode(',', $_SERVER[$header])[0]); // ambil IP pertama
            if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                return $ip;
            }
        }
    }

    // Fallback ke REMOTE_ADDR tanpa filter publik
    $ip = $_SERVER['REMOTE_ADDR'] ?? null;
    return filter_var($ip, FILTER_VALIDATE_IP) ? $ip : null;
}

Lainnya #

<?php
// FILTER_VALIDATE_DOMAIN — validasi nama domain
$valid   = filter_var("example.com", FILTER_VALIDATE_DOMAIN);   // "example.com"
$valid2  = filter_var("sub.example.com", FILTER_VALIDATE_DOMAIN); // valid
$invalid = filter_var("not a domain!", FILTER_VALIDATE_DOMAIN);  // false

// FILTER_VALIDATE_MAC — MAC address
$valid   = filter_var("AA:BB:CC:DD:EE:FF", FILTER_VALIDATE_MAC); // valid
$valid2  = filter_var("AA-BB-CC-DD-EE-FF", FILTER_VALIDATE_MAC); // valid

// FILTER_VALIDATE_REGEXP — validasi dengan regex kustom
$options = ['options' => ['regexp' => '/^\d{5}$/']] ; // kode pos 5 digit
$valid   = filter_var("12345", FILTER_VALIDATE_REGEXP, $options); // "12345"
$invalid = filter_var("1234",  FILTER_VALIDATE_REGEXP, $options); // false

// FILTER_VALIDATE_REGEXP vs preg_match langsung
// Gunakan preg_match untuk fleksibilitas lebih
// Gunakan FILTER_VALIDATE_REGEXP untuk konsistensi dengan pipeline filter lainnya

FILTER_SANITIZE_* — Sanitasi #

Filter sanitasi membersihkan nilai — menghapus atau encode karakter yang tidak diinginkan. Mereka tidak memvalidasi apakah nilai valid, hanya membersihkannya.

<?php
// FILTER_SANITIZE_EMAIL
// Hapus semua karakter selain yang valid di email
$bersih = filter_var("budi @ex ample.com!", FILTER_SANITIZE_EMAIL);
// "[email protected]" — spasi dan ! dihapus
// PERHATIAN: hasilnya belum tentu email valid! Tetap validasi setelah sanitasi.

// FILTER_SANITIZE_URL
$bersih = filter_var("https://example.com/path with spaces", FILTER_SANITIZE_URL);
// "https://example.com/path%20with%20spaces" — URL encode spasi
// Tapi ini tidak enkode semua karakter berbahaya — lebih baik gunakan urlencode/rawurlencode

// FILTER_SANITIZE_NUMBER_INT
// Hapus semua karakter selain digit, + dan -
$bersih = filter_var("Rp 15.000.000,-", FILTER_SANITIZE_NUMBER_INT);
// "15000000" — hapus semua non-digit kecuali + dan -

$bersih2 = filter_var("+62 812-3456-789", FILTER_SANITIZE_NUMBER_INT);
// "+62812345789"

// FILTER_SANITIZE_NUMBER_FLOAT
// Seperti NUMBER_INT tapi pertahankan titik desimal
$bersih = filter_var("Rp 15.000,50", FILTER_SANITIZE_NUMBER_FLOAT, [
    'flags' => FILTER_FLAG_ALLOW_FRACTION,  // izinkan titik/koma desimal
]);

// FILTER_SANITIZE_SPECIAL_CHARS
// Encode karakter HTML spesial menjadi entitas HTML
$bersih = filter_var('<script>alert("xss")</script>', FILTER_SANITIZE_SPECIAL_CHARS);
// "&#60;script&#62;alert(&#34;xss&#34;)&#60;/script&#62;"

// Tapi untuk output ke HTML, lebih baik gunakan:
$aman = htmlspecialchars($input, ENT_QUOTES | ENT_HTML5, 'UTF-8');

// FILTER_SANITIZE_ADD_SLASHES (PHP 7.3+, pengganti MAGIC_QUOTES)
$bersih = filter_var("It's a \"test\"", FILTER_SANITIZE_ADD_SLASHES);
// "It\'s a \"test\""
// PERHATIAN: addslashes() bukan cara yang benar untuk mencegah SQL injection!
// Gunakan prepared statement!

// FILTER_SANITIZE_ENCODED (URL encoding)
$bersih = filter_var("nama saya & teman", FILTER_SANITIZE_ENCODED);
// "nama%20saya%20%26%20teman"

// FILTER_DEFAULT (alias FILTER_UNSAFE_RAW)
// Tidak melakukan apapun — return nilai apa adanya
$raw = filter_input(INPUT_POST, 'data', FILTER_DEFAULT);
// Sama dengan $_POST['data'] tapi lebih aman dari undefined index

filter_input_array() — Validasi Banyak Input Sekaligus #

<?php
// Definisikan aturan validasi untuk seluruh form
$aturan = [
    'nama'       => FILTER_SANITIZE_SPECIAL_CHARS,
    'email'      => FILTER_VALIDATE_EMAIL,
    'umur'       => [
        'filter'  => FILTER_VALIDATE_INT,
        'options' => ['min_range' => 1, 'max_range' => 120],
    ],
    'website'    => [
        'filter' => FILTER_VALIDATE_URL,
        'flags'  => FILTER_FLAG_SCHEME_REQUIRED,
    ],
    'aktif'      => FILTER_VALIDATE_BOOLEAN,
    'skor'       => [
        'filter'  => FILTER_VALIDATE_FLOAT,
        'options' => ['min_range' => 0, 'max_range' => 100],
    ],
    'tags'       => [
        'filter' => FILTER_SANITIZE_SPECIAL_CHARS,
        'flags'  => FILTER_REQUIRE_ARRAY, // input adalah array
    ],
];

// Proses semua input POST sekaligus
$data = filter_input_array(INPUT_POST, $aturan);

// Cek hasil
if ($data === null) {
    // filter_input_array mengembalikan null jika superglobal tidak ada
    throw new \RuntimeException("Tidak ada data POST");
}

// $data sekarang:
// ['nama' => 'Budi', 'email' => 'budi@...', 'umur' => 28, ...]
// Field yang tidak valid: false
// Field yang tidak ada: null

$errors = [];
if ($data['email'] === false) {
    $errors['email'] = "Format email tidak valid";
}
if ($data['umur'] === false) {
    $errors['umur'] = "Umur harus antara 1 dan 120";
}
if ($data['website'] === false) {
    $errors['website'] = "URL tidak valid";
}

if (empty($errors)) {
    // Semua valid — proses data
    prosesRegistrasi($data);
}

Validasi Custom dengan Callback #

Untuk validasi yang tidak tersedia sebagai filter bawaan, gunakan FILTER_CALLBACK:

<?php
// Validasi nomor telepon Indonesia
$validasiTelepon = function(string $nomor): string|false {
    // Bersihkan: hapus spasi, tanda hubung, dan tanda kurung
    $bersih = preg_replace('/[\s\-\(\)]/', '', $nomor);

    // Konversi +62 ke 0
    if (str_starts_with($bersih, '+62')) {
        $bersih = '0' . substr($bersih, 3);
    }

    // Validasi: harus dimulai 08, panjang 10-13 digit
    if (!preg_match('/^08[1-9]\d{7,10}$/', $bersih)) {
        return false;
    }

    return $bersih; // return nilai yang sudah dibersihkan
};

$telepon = filter_var("0812-3456-789", FILTER_CALLBACK, ['options' => $validasiTelepon]);
// "081234567890" — valid dan dibersihkan

$invalid = filter_var("12345", FILTER_CALLBACK, ['options' => $validasiTelepon]);
// false

// Validasi kode pos Indonesia (5 digit)
$validasiKodePos = fn($kode) => preg_match('/^\d{5}$/', $kode) ? $kode : false;
$kodePos = filter_var("12345", FILTER_CALLBACK, ['options' => $validasiKodePos]);

// Validasi NIK (16 digit)
$validasiNIK = function(string $nik): string|false {
    $nik = trim($nik);
    return preg_match('/^\d{16}$/', $nik) ? $nik : false;
};

$nik = filter_var("3201234567890001", FILTER_CALLBACK, ['options' => $validasiNIK]);

Pola Validasi Form yang Lengkap #

<?php
class FormValidator
{
    private array $errors  = [];
    private array $data    = [];
    private array $input;

    public function __construct(array $input)
    {
        $this->input = $input;
    }

    public function required(string $field, string $label): static
    {
        $nilai = trim($this->input[$field] ?? '');
        if ($nilai === '') {
            $this->errors[$field] = "$label wajib diisi";
        } else {
            $this->data[$field] = $nilai;
        }
        return $this;
    }

    public function email(string $field, string $label): static
    {
        $nilai = filter_var(trim($this->input[$field] ?? ''), FILTER_VALIDATE_EMAIL);
        if ($nilai === false) {
            $this->errors[$field] = "$label tidak valid";
        } else {
            $this->data[$field] = $nilai;
        }
        return $this;
    }

    public function integer(string $field, string $label, int $min = PHP_INT_MIN, int $max = PHP_INT_MAX): static
    {
        $nilai = filter_var(
            $this->input[$field] ?? '',
            FILTER_VALIDATE_INT,
            ['options' => ['min_range' => $min, 'max_range' => $max]]
        );
        if ($nilai === false) {
            $this->errors[$field] = "$label harus angka antara $min dan $max";
        } else {
            $this->data[$field] = $nilai;
        }
        return $this;
    }

    public function url(string $field, string $label): static
    {
        $raw   = trim($this->input[$field] ?? '');
        $nilai = filter_var($raw, FILTER_VALIDATE_URL);
        $scheme = parse_url($raw, PHP_URL_SCHEME);

        if ($nilai === false || !in_array($scheme, ['http', 'https'], true)) {
            $this->errors[$field] = "$label harus URL http/https yang valid";
        } else {
            $this->data[$field] = $nilai;
        }
        return $this;
    }

    public function custom(string $field, string $label, callable $validator): static
    {
        $nilai = filter_var(
            $this->input[$field] ?? '',
            FILTER_CALLBACK,
            ['options' => $validator]
        );
        if ($nilai === false) {
            $this->errors[$field] = "$label tidak valid";
        } else {
            $this->data[$field] = $nilai;
        }
        return $this;
    }

    public function isValid(): bool
    {
        return empty($this->errors);
    }

    public function getErrors(): array
    {
        return $this->errors;
    }

    public function getData(): array
    {
        return $this->data;
    }
}

// Penggunaan
$validator = new FormValidator($_POST);
$validator
    ->required('nama',    'Nama')
    ->email('email',      'Email')
    ->integer('umur',     'Umur', min: 1, max: 120)
    ->url('website',      'Website')
    ->custom('telepon',   'Telepon', fn($v) => preg_match('/^08\d{9,11}$/', preg_replace('/\D/', '', $v))
        ? preg_replace('/\D/', '', $v) : false);

if (!$validator->isValid()) {
    http_response_code(422);
    echo json_encode(['errors' => $validator->getErrors()]);
    exit;
}

$data = $validator->getData();
simpanUser($data);

Anti-Pattern Validasi yang Sering Ditemui #

<?php
// ✗ Anti-pattern 1: akses superglobal langsung tanpa validasi
$email = $_POST['email']; // undefined index, tidak divalidasi, tidak disanitasi

// ✓ Gunakan filter_input + validasi
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
if ($email === false || $email === null) {
    $errors['email'] = "Email tidak valid";
}

// ✗ Anti-pattern 2: gunakan == false untuk cek validasi
$email = filter_var($input, FILTER_VALIDATE_EMAIL);
if ($email == false) { } // "" == false juga true! Email kosong lolos!

// ✓ Selalu gunakan === false
if ($email === false) {
    $errors['email'] = "Email tidak valid";
}

// ✗ Anti-pattern 3: sanitasi saja tanpa validasi
$email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
simpanEmail($email); // mungkin hasilnya bukan email valid!

// ✓ Sanitasi lalu validasi (atau validasi saja yang sudah cukup)
$email = filter_var(
    filter_var($_POST['email'], FILTER_SANITIZE_EMAIL),
    FILTER_VALIDATE_EMAIL
);

// ✗ Anti-pattern 4: gunakan FILTER_SANITIZE_STRING (deprecated PHP 8.1)
$nama = filter_var($input, FILTER_SANITIZE_STRING); // deprecated!

// ✓ Gunakan htmlspecialchars untuk output ke HTML
$nama = htmlspecialchars(trim($input), ENT_QUOTES | ENT_HTML5, 'UTF-8');

// ✗ Anti-pattern 5: menganggap filter_var cukup untuk mencegah SQL injection
$id = filter_var($_GET['id'], FILTER_VALIDATE_INT);
$db->query("SELECT * FROM users WHERE id = $id"); // masih berbahaya!

// ✓ Validasi + prepared statement
$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
if ($id === false || $id === null) {
    http_response_code(400);
    exit;
}
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);

Ringkasan #

  • filter_input() lebih baik dari $_POST['nama'] — mengambil dan memfilter sekaligus, tidak melempar warning jika key tidak ada, dan lebih eksplisit soal sumber data.
  • === false bukan == false — filter validasi mengembalikan nilai asli (bisa string kosong, 0, false literal) atau false jika invalid. String kosong "" sama dengan false jika dibandingkan dengan ==.
  • Sanitasi ≠ ValidasiFILTER_SANITIZE_EMAIL membersihkan karakter tapi tidak memastikan hasilnya adalah email valid. Selalu validasi setelah sanitasi, atau cukup validasi saja.
  • FILTER_VALIDATE_BOOLEAN jauh lebih cerdas dari casting (bool) — ia mengenali "true", "yes", "on", "1" sebagai true dan kebalikannya sebagai false. Sangat berguna untuk env variable dan konfigurasi.
  • filter_input_array() untuk validasi form sekaligus — definisikan aturan sebagai array, proses semua input dalam satu pemanggilan, hasilkan array dengan nilai tervalidasi atau false/null.
  • FILTER_CALLBACK untuk validasi custom — gunakan closure sebagai validator, kembalikan nilai yang dibersihkan jika valid atau false jika tidak.
  • Filter bukan pengganti prepared statement — meski sudah memvalidasi integer dengan FILTER_VALIDATE_INT, tetap gunakan prepared statement untuk query database. Validasi mencegah logika salah, prepared statement mencegah SQL injection.
  • FILTER_SANITIZE_STRING sudah deprecated sejak PHP 8.1 — gunakan htmlspecialchars() untuk escape output HTML, atau strip_tags() untuk menghapus tag HTML.

← Sebelumnya: Math   Berikutnya: Array Functions →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact