5. Data Form 3

PHP: Validasi Data Form [3/3]

Pada dua pertemuan sebelumnya kita telah menyelesaikan proses pemeriksaan untuk semua peraturan yang kita buat. Kita juga telah mengubah beberapa tipe inputan pada form HTML menjadi type="text" untuk mempermudah pemeriksaan.

Pada pertemuan kali ini, kita akan melanjutkan proses validasi form tersebut. Yaitu dengan membuat pesan error dan menampilkannya di halaman form HTML.

Siapkan senjata, nyamankan tempat duduk, seduh kopi.

Karena kita akan mulai kembali menulis kode.

Mempersingkat Kode

Sebelum kita mulai membuat pesan error. Terlebih dahulu kita akan merapikan dan memepersingkat kode dari fungsi validasi().

Pada kode program sebelumnya, ketika kita ingin memanggil fungsi pemeriksaan, kita selalu melakukan logika percabangan dengan perintah if untuk memanggil fungsi pemeriksaan yang sesuai:

  • Untuk peraturan “required” kita panggil fungsi lolosRequired().
  • Untuk peraturan “numeric” kita panggil fungsi lolosNumeric().
  • Untuk peraturan “url” kita panggil fungsi lolosUrl().

Lalu bagaimana jika fungsi pemeriksaannya ada banyak sekali? Apakah kita juga akan menulis if-else sebanyak peraturan yang ada?

Berhubung nama fungsi dan nama peraturan memiliki pola yang jelas:

  • Yaitu nama fungsi selalu diawali kata “lolos”.
  • Nama fungsi selalu diikuti nama peraturan yang huruf pertamanya telah dibuat kapital.
  • Sehingga nama fungsi bisa kita generate menggunakan kode program.
  • Dengan begitu kita tidak perlu melakukan if-else secara manual.

Langsung saja buka file helper/fungsi-validasi.php.

Masuk ke fungsi validasi().

Hapus semua kode pada foreach() ke dua, lalu timpa dengan kode yang baru seperti berikut:

<?php

function validasi(array $listInput)
{
    ...
    foreach ($listInput as $input => $listPeraturan) {
        ...
        foreach ($listPeraturan as $peraturan) {
            echo "-> Peraturan <strong>{$peraturan}</strong>: ";

            $namaFungsi = 'lolos' . ucfirst($peraturan);

            echo "Panggil fungsi <strong>{$namaFungsi}</strong>";
            echo "<br>";
        }
        ...
    }
}

Jalankan halaman web, klik tombol Sumbit. Kita akan mendapatkan output kira-kira sebagai berikut:

Pada output di atas, kita telah berhasil membuat variabel $namaFungsi yang berisi nama fungsi pemeriksaan yang akan kita panggil sesuai dengan isi dari variabel $peraturan.

Memanggil fungsi pemeriksaan secara dinamis

Setelah berhasil membuat variabel $namaFungsi. Kita bisa langsung memanggil fungsi yang sesuai secara dinamis dengan menambahkan tanda kurung () setelah variabel $namaFungsi().

<?php

$namaFungsi = "lolosUrl";
$namaFungsi("https://jagongoding.com");

Kode program di atas akan memanggil fungsi apa pun yang sesuai dengan isi dari variabel $namaFungsi().

Berikut ini kode programnya secara lebih lengkap:

<?php

function validasi(array $listInput)
{
    ...
    foreach ($listInput as $input => $listPeraturan) {
        ...
        foreach ($listPeraturan as $peraturan) {
            echo "-> Peraturan <strong>{$peraturan}</strong>: ";

            $namaFungsi = 'lolos' . ucfirst($peraturan);
            $lolos = $namaFungsi($request[$input]);

            echo $lolos ? 'Lolos' : 'Tidak Lolos';
            echo "<br>";
        }
        ...
    }
}

Jika kita mengeksekusi hasil kodingan kita, kita akan mendapatkan output yang sama persis dengan hasil dari pertemuan validasi form bagian ke-2. Hanya saja, kode programmnya menjadi lebih singkat.

Pesan Error

Selanjutnya kita akan masuk ke dalam inti pembahasan: yaitu membuat dan menampilkan pesan error dari validasi form PHP yang kita bangun.

Agar kode program kita menjadi lebih terstruktur, silakan buat satu file baru dengan nama helper/fungsi-pesan-error.php. File tersebut nantinya akan kita gunakan untuk men-generate pesan error dari setiap peraturan.

validasi-form/
├── helper/
│   └── fungsi-pesan-error.php
│   └── fungsi-validasi.php
├── form.php
└── proses.php

Buka file helper/fungsi-pesan-error.php, lalu tulis kode sebagai berikut:

<?php

$listPesanError = [
    'required' => function ($field) {
        return "Field {$field} harus diisi.";
    },
    'email' => function ($field) {
        return "Field {$field} harus berupa email yang valid.";
    },
    'numeric' => function ($field) {
        return "Field {$field} harus berupa angka numerik.";
    },
    'url' => function ($field) {
        return "Field {$field} harus berupa url yang valid.";
    },
    'username' => function ($field) {
        return "Field {$field} hanya boleh berisi huruf, angka, dan underscore.";
    }
];

Penjelasan:

Memanggil Pesan Error Yang Sesuai

Setelah membuat list fungsi untuk men-generate pesan error. Tahap selanjutnya adalah kita akan memanggil fungsi-fungsi tersebut jika ternyata ada validasi yang tidak lolos.

Langkah yang pertama, pada file helper/fungsi-validasi.php, hapus semua perintah echo yang telah kita tulis sebelumhya.

Yang kedua, tambahkan kode berikut di bagian atas file untuk bisa mengakses file helper/fungsi-pesan-error.php.

<?php

require_once 'fungsi-pesan-error.php';

Setelah itu, pada fungsi validasi(), setelah pendeklarasian variabel $request, tambahkan beberapa 2 variabel baru bernama $errors dan $listPesanError.

<?php

# variabel yang akan berisi kumpulan pesan error
$errors = [];
# mengakses variabel $listPesanError yang ada di file `fungsi-pesan-error.php`
global $listPesanError;

Penjelasan:

  • Variabel $errors nantinya akan menjadi array asosiatif yang akan menampung tiap pesan error yang ada.
  • Perintah global $listPesanError berfungsi agar fungsi validasi() bisa mengakses variabel $listPesanError yang berada di luar scope lokal fungsi.
  • Lebih lengkapnya silakan baca tentang Ruang Lingkup Variabel pada PHP.

Selanjutnya, ubah isi dari foreach() kedua dari fungsi validasi() menjadi seperti berikut:

<?php

...
foreach ($listInput as $input => $listPeraturan) {
    # perulangan untuk sub array (berisi nama peraturan)
    foreach ($listPeraturan as $peraturan) {
        $namaFungsi = 'lolos' . ucfirst($peraturan);
        $lolos = $namaFungsi(@$request[$input]);

        # jika tidak lolos
        if (!$lolos) {
            if (!is_array(@$errors[$input])) {
                $errors += [$input => []];
            }
            
            array_push($errors[$input], $listPesanError[$peraturan]($input));
        }
    }
}
...

Penjelasan:

  • Di sini kita melakukan pemeriksaan apakah hasil kembalian dari fungsi $namaFungsi() bernilai true atau false
  • Jika bernilai false, kita akan memanggil fungsi pesan error pada variabel $listPesanError.
  • Kita melemparkan variabel $input ke fungsi $listPesanError[$peraturan] yang berisi nama field dari form HTML
  • Hasil kembalian yang kita dapat akan kita kumpulkan pada variabel $errors dikelompokkan berdasarkan nama field-nya.
  • Kode program di atas akan menjadi lebih jelas ketika kita menampilkan variabel $errors dengan perintah print_r.

Mengembalikan variabel $errors

Langkah yang terakhir yang kita lakukan untuk mengubah fungsi validasi() adalah: mengembalikan variabel $errors.

<?php

function validasi(array $listInput)
{
    ...

    return $errors;
}

Memeriksa isi dari variabel $errors

Buka file proses.php. Ubah cara pemanggilan fungsi validasi() menjadi seperti berikut:

<?php

$errors = validasi($peraturan);

echo "<pre>";
print_r($errors);
echo "</pre>";

Coba jalankan form, biarkan semua input kosong, lalu klik tombol Submit.

Berikut kira-kira output yang kita dapat:

Coba kembali ke halaman form, isi beberapa input, dan lihat bagaimana output dari variabel $errors.

Sampai sini inti dari validasi form yang kita buat telah selesai. Tinggal satu hal lagi yaitu: menampilkan pesan error.

Menampilkan Pesan Error Dengan Variabel $_GET (Query String)

Setelah kita berhasil menyimpan pesan error dalam variabel $errors pada file proses.php.

Kita akan menampilkan pesan error tersebut di dalam form HTML.

Pertanyaannya adalah: bagaimana caranya mengirimkan variabel yang ada pada file proses.php, ke dalam file form.php?

Secara umum, ada dua cara:

  1. Menggunakan query string
  2. Menggunakan session PHP (direkomendasikan)

Kita akan coba menggunakan cara yang pertama lebih dahulu.

Redirect ke file form.php dengan membawa pesan error

Buka file proses.php.

Hapus tag <pre></pre> yang sebelumnya kita gunakan untuk menampilkan isi dari variabel $errors.

Lalu ganti dengan blok if berikut:

<?php

if (count($errors) > 0) {
    $old = $_REQUEST;
    $queryString = http_build_query([
        'errors' => $errors,
        'old' => $old
    ]);
    
    header("Location: form.php?{$queryString}");
    die();
}

# di sini kita bisa melakukan proses yang harus dilakukan
# jika tidak terjadi error validasi apa pun.

Penjelasan:

  • Pertama kita periksa apakah array $errors ada isinya atau tidak.
  • Jika ada, kita mulai membuat variabel $queryString yang berisi variabel $old dan $errors.
  • Variabel $old berisi semua nilai input dari request form sebelumnya. Kita akan kirim ulang nilai-nilai tersebut agar user tidak perlu mengisi ulang input yang sebelumnya sudah ia isi.
  • Fungsi header("Location: ...") akan me-redirect request ke halaman form.php, akan tetapi dengan query string yang telah kita buat.
  • Fungsi die() dipanggil agar script berhenti di sana, dan tidak mengeksekusi kode program di bawah if.

Menangkap dan menampilkan pesan error

Setelah kita berhasil me-redirect dari halaman proses.php kembali ke halaman form.php ketika terjadi error. Dan hasil redirect tersebut juga membawa pesan error yang berkaitan, sekarang yang kita harus lakukan adalah menangkap variabel kiriman tersebut dan menampilkannya.

Yang pertama, buka file form.php.

Kemudian pada bagian paling atas, sebelum tag <!DOCTYPE html>, tambahkan kode program berikut:

<?php
    $old = (object) @$_GET['old'];
    $errors = (object) @$_GET['errors'];
?>

Penjelasan::

  • Kode program di atas akan membuat 2 buah variabel yaitu variabel $old dan $errors yang diambil dari query string.
  • Tidak hanya mengambil nilai saja, akan tetapi kode program di atas juga mengkonversi nilai array menjadi object dari stdClass.
  • Apakah wajib dikonversi? Tidak. Hanya saja saya lebih suka mengaskses data dari stdClass dibandingkan dari array asosiatif.

Pertahankan value yang lama.

Kita telah menangkan variabel $old yang berisi nilai inputan terakhir user.

Untuk menampilkannya, kita harus mengubah setiap tag <input> pada file form.php, lalu menambahkan atribut value menjadi seperti berikut:

<input type="text" name="nama" value="<?php echo @$old->nama ?>" placeholder="Masukkan nama">

Lakukan hal di atas untuk semua tag <input> yang lainnya. Jangan lupa ubah @$old->nama dengan nilai yang sesuai.

Tampilkan error.

Setelah berhasil mempertahankan nilai form dari request sebelumnya. Kita bisa melakukan hal yang sama untuk menampilkan pesan error. Hanya saja variabel yang kita gunakan adalah variabel $errors.

Langsung saja, di bawah setiap tag <input>, tambahkan kode berikut:

<?php
if (@$errors->nama):?>
    <div style="color: red"><?php echo $errors->nama[0] ?></div>
<?php
endif; ?>

Ulangi kode program di atas pada setiap <input>, jangan lupa sesuaikan atribut nama dengan field yang bersangkutan.

Hasil Akhir

Setelah berhasil tanpa error, kita akan mendapatkan hasil akhir seperti berikut:

Kode Program Lengkap

Kode program lengkap dari pertemuan ini bisa anda akses di repositori github berikut:

https://github.com/jagongoding-com/php-web-dinamis/tree/master/03-validasi-form

Pembahasan Selanjutnya

Insyaallah pada pertemuan selanjutnya kita akan membahas tentang upload file pada PHP.

Ikuti terus serial tutorial PHP web dinamis ini, ya!

Jangan lupa share ke teman-teman kalian! Terima kasih banyak.