PHP Untuk Web Dinamis

Site: Elearning Muhidin Saimin
Course: Web Development
Book: PHP Untuk Web Dinamis
Printed by: Guest user
Date: Tuesday, 17 September 2024, 3:35 AM

1. Form

PHP: Membuat Dan Menangani Form

Ini adalah seri Tutorial PHP yang ketiga di Jago Ngoding. Kita telah membahas Tutorial PHP Tingkat Dasar, dan juga Tingkat Menengah. Pada seri lanjutan ini, kita akan mempelajari bahasa pemrograman PHP untuk membangun sebuah web dinamis.

Apa itu Web Dinamis?

Secara umum, web itu terbagi menjadi 2: web statis dan web dinamis. Web statis adalah web yang dibangun dengan kode HTML yang bersifat tetap (atau statis). Kontennya tidak berubah. Itu-itu saja. Sedangkan web dinamis: ia adalah suatu web yang kontennya berubah-ubah. Web dinamis biasanya memiliki kemampuan: login, baca data, tambah data, ubah data, dan hapus data.

PHP merupakan salah satu bahasa pemrograman populer untuk membangun sebuah web dinamis.

Apa itu Form?

Untuk membangun sebuah web dinamis, kita membutuhkan inputan data. Di antara inputan data yang paling dasar dalam halmaan web adalah: form.

Apa itu Form?

Form merupakan sintaks HTML yang berisi kumpulan kolom isian data, misal:

  • form login yang berisi isian nama pengguna dan kata sandi.
  • form pendaftaran yang berisi isian nama, jenis kelamin, tanggal lahir, alamat, surel, dan lain-lain.

Dalam pembuatan web dinamis, kita bisa melakukan pengiriman data dari form HTML untuk kemudian data tersebut akan diproses lebih lanjut oleh bahasa pemrograman PHP.

Membuat Form Sederhana

Bahasa yang kita gunakan untuk membuat form untuk web dinamis adalah HTML.

  1. Silakan anda membuat file dengan nama form.php
  2. Lalu isi dengan kode program di bawah ini:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Membuat Form Sederhana</title>
</head>
<body>
    <form>
        <div>
            <label>Nama</label> <br>
            <input name="nama" type="text" placeholder="Masukkan nama">
        </div>
        <div>
            <label>Alamat</label> <br>
            <input name="alamat" type="text" placeholder="Masukkan alamat">
        </div>
        <div>
            <button>Submit</button>
        </div>
    </form>
</body>
</html>

Kode program di atas akan membuat 2 buah input teks:

  1. Input bertipe teks dengan name nama
  2. Input bertipe teks dengan name alamat

Jika kita eksekusi file form.php di atas, output yang kita dapat adalah seperti berikut:

Menampilkan Data Yang Dikirim Melalui Form

Kita telah berhasil membuat sebuah form dengan 2 buah isian data. Sekarang:

  1. Kita coba isi inputan nama dan inputan alamat.
  2. Lalu kita klik tombol submit.
  3. Setelah itu kita perhatikan url browser kita.

Misal saya isi “Nurul Huda” untuk nama, dan “Surabaya” untuk alamat. Maka saya mendapatkan url seperti berikut:

localhost/form.php?nama=Nurul+Huda&alamat=Surabaya

Bagian url setelah tanda ? dinamakan query string. Dan pada pembahasan tentang variabel bawaan PHP, kita telah mempelajari bagaimana cara mengakses query string dengan variabel $_GET.

Untuk menampilkan data hasil inputan, ikuti langkah-langkah berikut:

  1. Cari tag </form> dari kode di atas

  2. Buat baris baru.

  3. Lalu tambahkan kode program berikut:

    <?php # membuka tag PHP
    
    $nama = @$_GET['nama'];
    $alamat = @$_GET['alamat'];
    
    # di sini nanti kita akan tampilkan variabel $nama dan $alamat
    
    # jangan lupa tutup tag PHP
    ?>
    

    Kode program di atas berfungsi untuk membaca data yang berada pada query string. Tanda @ sebelum variabel $_GET berfungsi untuk mengubah nilai menjadi null jika key nama atau pun alamat tidak tersedia pada array $_GET. Lebih lengkapnya pernah kita pelajari pada pembahasan hal-hal yang dianggap true atau dianggap false dalam PHP.

  4. Selanjutnya, tambahkan kode program berikut setelah komentar # di sini nanti kita akan tampilkan variabel $nama dan $alamat.

    <?php
    # ...
    # ...
    
    # di sini nanti kita akan tampilkan variabel $nama dan $alamat
    if ($nama) {
        echo "<strong>Nama:</strong> {$nama} <br>";
    }
    
    if ($alamat) {
        echo "<strong>Alamat:</strong> {$alamat} <br>";
    }
    ?>
    

    Kode program di atas akan memeriksa apakah variabel $nama dan $alamat tidak kosong. Jika memang tidak kosong alias ada isinya, maka variabel-variabel tersebut akan ditampilkan.

Berikut ini output yang saya dapatkan:

Anda bisa coba untuk mengisi hanya inputan nama saja, atau hanya inputan alamat saja. Lalu lihat bagaimana output yang anda dapatkan.

Perbedaan Metode GET dan POST

Terdapat beberapa metode pengiriman data dalam protokol HTTP/HTTPS. Akan tetapi yang didukung oleh HTML hanya dua saja: yaitu metode GET dan metode POST [1].

Form pada HTML secara default akan menggunakan metode GET untuk mengirimkan data. Seperti yang telah kita lakukan di atas.

Akan tetapi, kita bisa mengatur metode apa yang harus digunakan oleh Form untuk mengirim data dengan menambahkan atribut method pada tag <form>.

Seperti contoh berikut:

<form method="POST">
  <!-- inputan -->
</form>

Di situ tag <form> akan mengirimkan data ke server dengan menggunakan metode POST.

Lalu, apa bedanya POST dan GET?

Bedanya adalah:

  • Metode GET akan menampilkan semua data dalam url (yang kemudian disebut sebagai query string).
  • Sedangkan POST, ia akan menyimpan data di dalam body request tanpa menampilkannya secara langsung di dalam URL.

Bayangkan jika sebuah form login yang berisi kata sandi dikirim melalui metode GET? Tentu saja kata sandi tersebut akan terekpos di dalam URL dan ini akan memudahkan peretas untuk mencuri data.

Berikut ini adalah contoh form yang menggunakan metode POST.

<form method="POST">
    <div>
        <label>Email</label> <br>
        <input name="email" type="email" placeholder="Masukkan email">
    </div>
    <div>
        <label>Kata Sandi</label> <br>
        <input name="password" type="password" placeholder="Masukkan kata sandi">
    </div>
    <div>
        <button>Login</button>
    </div>
</form>
<?php # membuka tag PHP

$email = @$_POST['email'];
$password = @$_POST['password'];

# jangan lupa tutup tag PHP
if ($email) {
    echo "<strong>Email:</strong> {$email} <br>";
}

if ($password) {
    echo "<strong>Kata Sandi:</strong> {$password} <br>";
}
?>

Penjelasan:

  • Kita menambahkan atribut method dengan nilai "POST" pada tag <form>
  • Kita menggunakan variabel $_POST sebagai ganti dari variabel $_GET

Menggunakan Variable $_REQUEST

Seperti yang pernah kita pelajari pada pembahasan variabel bawaan PHP. Kita bisa menggunakan variabel $_REQUEST untuk memanggil data yang dikirim melalui form, baik data tersebut dikirim dengan metode GET mau pun menggunakan metode POST.

Sehingga variabel $_REQUEST bisa menjadi pengganti dari variabel $_GET mau pun variabel $_POST.

Mengirim Data ke File Yang Berbeda

Pada 2 contoh form yang telah kita buat, kita menggabungkan antara halaman input dan halaman proses. Sehingga data yang kita tampilkan pun masih berada dalam file yang sama.

Sebenarnya, kita bisa memisahkan antara halaman input dan halaman presentasi data.

Kita bisa melakukannya dengan menambahkan atribut action pada tag <form>.

<form action="proses.php">
  <!-- input -->
</form>

Isi dari atribut action bisa berupa nama file, dan bisa juga berupa url lengkap.

Sebagai contoh, silakan buat dua file seperti berikut:

belajar-form
├── form-login.php
└── proses-login.php

Lalu isi file form-login.php dengan kode HTML berikut:

<form method="POST" action="proses-login.php">
    <div>
        <label>Email</label> <br>
        <input name="email" type="email" placeholder="Masukkan email">
    </div>
    <div>
        <label>Kata Sandi</label> <br>
        <input name="password" type="password" placeholder="Masukkan kata sandi">
    </div>
    <div>
        <button>Login</button>
    </div>
</form>

Tag <form> pada kode program di atas memiliki 2 buah atribut:

  • Atribut method untuk menentukan metode yang digunakan, di sini kita menggunakan metode POST
  • Atribut action yang merepresentasikan file/alamat di mana data akan dikirim ketika form di-submit.

Kemudian, kita bisa menampilkan dan memproses data yang dikirim ke dalam file proses-login.php sebagai berikut:

<?php

$email = @$_REQUEST['email'];
$password = @$_REQUEST['password'];

if ($email !== 'fulan@gmail.com') {
  die("Email tidak terdaftar!");
}

if ($password !== 'kerjadarirumah') {
  die("Password salah!");
}

# jika lolos alias email dan password nya benar
echo "Selamat {$email}, anda berhasil login! :)";

# tag php tidak perlu ditutup karena ia tidak bercampur dengan bahasa lainnya

Contoh Berbagai Macam Tipe Isian Data

Di dalam HTML, terdapat beberapa tipe isian data. Kita telah mencoba beberapa seperti text, email, dan password. Tapi masih ada beberapa hal lagi seperti: select, textarea, checkbox, radio, dan sebagainya.

Berikut ini adalah contoh bagaimana sintaks form-nya dan bagaimana datanya dikirimkan di dalam PHP.

Pertama, buat 2 file baru sebagai berikut:

belajar-form
├── form-pendaftaran.php
└── proses-pendaftaran.php

Kode program untuk file form-pendaftaran.php:

<form action="proses-form-pendaftaran.php" method="POST">
    <div>
        <label>Nama</label> <br>
        <input type="text" name="nama">
    </div>
    <div>
        <label>Email</label> <br>
        <input type="email" name="email">
    </div>
    <div>
        <label>Usia</label> <br>
        <input type="number" name="usia">
    </div>
    <div>
        <label>Tanggal Lahir</label> <br>
        <input type="date" name="tanggal_lahir">
    </div>
    <div>
        <label>Alamat</label> <br>
        <textarea name="alamat"></textarea>
    </div>
    <div style="margin-bottom: 1rem;">
        <label>Jenis Kelamin</label> <br>
        <input type="radio" name="jenis_kelamin" value="l"> Laki-Laki <br>
        <input type="radio" name="jenis_kelamin" value="p"> Perempuan
    </div>
    <div style="margin-bottom: 1rem;">
        <label>Status</label> <br>
        <select name="status">
            <option value="lajang">Lajang</option>
            <option value="menikah">Menikah</option>
        </select>
    </div>
    <div style="margin-bottom: 1rem;">
        <label>Hobi</label> <br>
        <input type="checkbox" name="hobi[]" value="berenang"> Berenang <br>
        <input type="checkbox" name="hobi[]" value="sepak bola"> Sepak Bola <br>
        <input type="checkbox" name="hobi[]" value="bulu tangkis"> Bulu Tangkis <br>
        <input type="checkbox" name="hobi[]" value="ngoding"> Ngoding <br>
    </div>
    <div>
        <button>Submit</button>
    </div>
</form>

Kode program untuk file proses-pendafataran.php. Kita langsung tampilkan menggunakan perintah print_r saja agar outputnya jelas:

<pre>
<?php print_r($_REQUEST); ?>
</pre>

Output form html:

Output data:

Array
(
    [nama] => Fulan bin Fulan
    [email] => fulan@outlook.com
    [usia] => 80
    [tanggal_lahir] => 1940-03-27
    [alamat] => Jl. Dr. Ir. H. Soekarno, Semolowaru, Surabaya
    [jenis_kelamin] => l
    [status] => menikah
    [hobi] => Array
        (
            [0] => berenang
            [1] => ngoding
        )

)

Pembahasan Selanjutnya

Kita telah belajar cara sederhana untuk membuat form dan menampilkan datanya dengan PHP. Akan tetapi, untuk lebih memantapkan lagi tentang apa yang kita pelajari, insyaallah pada pertemuan selanjutnya kita akan membahas bagaimana cara membuat kalkulator sederhana (plus kalkulator scientific) pada PHP.

Jangan lupa share tutorial ini, ya! Terima kasih banyak.

Referensi

[1] https://dev.to/moz5691/method-override-for-put-and-delete-in-html-3fp2 - diakses tanggal 27 Maret 2020


2. Membuat Kalkulator

PHP: Membuat Kalkulator Biasa dan Scientific Sederhana

Pada pertemuan sebelumnya kita telah mempelajari tentang cara membuat form di PHP dan bagaimana cara memprosesnya. Kita juga telah mencoba contoh-contoh sederhana dari beberapa jenis isian form HTML.

Untuk lebih memantapkan pemahaman dan menguatkan gambaran umum tentang bagaimana mengelola data dari Form, pada pertemuan kali ini insyaallah kita akan mempelajari bagaimana cara membuat kalkulator dengan PHP.

Kita akan mencoba untuk membuat dua buah kalkulator:

  • Kalkulator sederhana
  • Kalkulator Scientific (yang juga sederhana)

Persiapan

Agar bisa mengikuti tutorial ini dengan baik, saya anggap anda telah:

Kenapa? Karena di dalam tutorial ini akan melibatkan hal-hal dasar seperti macam-macam tipe data PHPmacam-macam operatorlogika percabangan dan juga variabel casting.

Buat File PHP

Langsung saja, sebelum memulai ngoding, kita buat dulu 2 buah file php sebagai berikut:

kalkulator/
├── biasa.php
└── scientific.php

Masing-masing dari 2 file tersebut akan kita gunakan untuk menampilkan form, sekaligus juga menampilkan hasilnya.

Membuat Form Kalkulator Sederhana

Kita akan mulai dari membuat form untuk tipe kalkulator pertama. Kalkulator pertama ini hanya berupa dari dua buah inputan bertipe data number, dan satu inputan berupa dropdown (select) yang berisi operator aritmatika.

Langsung saja, buka file biasa.php lalu isi sebagai berikut:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Kalkulator Biasa | Jago Ngoding</title>
</head>
<body>
    <h1>Kalkulator Biasa</h1>
    <form>
        <input type="number" name="a" placeholder="Bilangan a">

        <select name="operator">
            <option selected disabled>Pilih Operator</option>
            <option value="+">+</option>
            <option value="-">-</option>
            <option value="*">*</option>
            <option value="/">/</option>
        </select>

        <input type="number" name="b" placeholder="Bilangan b">

        <div style="margin-top: 1rem">
            <button type="button" onclick="location.href = '?clear'">Clear</button>
            <button type="submit">Hitung</button>
        </div>
    </form>
</body>
</html>

Kode program di atas akan menghasilkan sebuah form sederhana seperti ini:

Proses Kalkulator Sederhana

Seperti yang telah kita bahas pada pertemuan sebelumnya, bahwa jika atribut action dan method pada tag <form> tidak didefinisikan, itu artinya secara bawaan ia akan menggunakan method GET, dan akan menjadikan “diri sendiri” sebagai action.

Di bawah tag <form>, silakan tambahkan kode program berikut:

<?php
if ($_GET): ?>
<pre><?php echo print_r($_GET) ?></pre>
<?php
endif; ?>

Coba isi setiap input dari form yang telah kita buat, lalu klik tombol Hitung.

Kita akan mendapatkan output kira-kira seperti ini:

Mempertahankan value form sebelumnya

Jika kita perhatikan, setelah kita klik tombol Hitung, maka kita akan mendapatkan output berupa isi dari variabel $_GET. Akan tetapi, kita saksikan bahwa 3 input yang sudah kita isi, ia kembali kosong seperti tidak pernah ada data sebelumnya.

Pada step ini, kita akan coba untuk mempertahankan nilai dari inputan sebelumnya.

Ubah ketiga input dari form kalkulator menjadi seperti ini:

<input type="number" name="a" placeholder="Bilangan a" value="<?php echo @$_GET['a'] ?>">

<select name="operator">
    <option <?php echo !@$_GET['operator'] ? 'selected' : '' ?> disabled>Pilih Operator</option>
    <option <?php echo @$_GET['operator'] === '+' ? 'selected' : '' ?> value="+">+</option>
    <option <?php echo @$_GET['operator'] === '-' ? 'selected' : '' ?> value="-">-</option>
    <option <?php echo @$_GET['operator'] === '*' ? 'selected' : '' ?> value="*">*</option>
    <option <?php echo @$_GET['operator'] === '/' ? 'selected' : '' ?> value="/">/</option>
</select>

<input type="number" name="b" placeholder="Bilangan b" value="<?php echo @$_GET['b'] ?>">

Penjelasan:

  • Kita menambahkan attribut value untuk 2 tag <input>. Atribut tersebut akan mendefinisikan nilai dari input yang bersangkutan
  • Kita menambahkan atribut selected pada tag <option> yang terpilih untuk menandakan mana <option> yang aktif. Itu dikarenakan tag <select> tidak mendukung atribut value
  • Kita menggunakan tanda @ sebelum variabel $_GET agar jika key yang kita panggil tidak tersedia, ia otomatis bernilai null dan tidak terjadi error.
  • Kita menggunakan percabangan ternary untuk mempersingkat kode program.

Logika kalkulator

Setelah kita mengetahui isi dari variabel $_GET dengan menggunakan perintah print_r, kita juga telah mempertahankan nilai masing-masing input ketika tombol Hitung ditekan. Sekarang saatnya kita mulai menulis kode untuk menyelesaikan logika kalkulator.

Logikanya sederhana: kita akan memeriksa masing-masing operator dan akan melakukan operasi yang sesuai dengan operator yang dipilih.

Hapus kode program berikut:

<?php
if ($_GET): ?>
<pre><?php echo print_r($_GET) ?></pre>
<?php
endif; ?>

Lalu ganti seperti ini:

<?php
if ($_GET):
    $a = (double) @$_GET['a'];
    $b = (double) @$_GET['b'];
    $operator = @$_GET['operator'];
    
    switch ($operator) {
        case '+':
            $hasil = $a + $b;
            break;
        case '-':
            $hasil = $a - $b;
            break;
        case '*':
            $hasil = $a * $b;
            break;
        case '/':
            $hasil = $a / $b;
            break;
    }
    ?>
    <div style="margin-top: 1rem">
    Hasil: <strong><?php echo $hasil ?></strong>
    </div>
    <?php
endif; ?>

Setelah itu kalkulator yang telah kita buat sudah bisa dicoba:

Membuat Form Kalkulator Scientific (Sederhana)

Oke, kita telah sukses membuat kalkulator sederhana dengan PHP.

Sekarang kita akan membuat kalkulator scientific, yang juga sederhana.

Langsung saja buka file scientific.php dan buat form HTML-nya sebagai mana berikut:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Kalkulator Scientific Sederhana | Jago Ngoding</title>
</head>
<body>
    <h1>Kalkulator Scientific Sederhana</h1>
    <form>
        <input type="text" name="ekspresi" placeholder="Ekspresi aritmatika" value="<?php echo @$_GET['ekspresi'] ?>">

        <div style="margin-top: 1rem">
            <button type="button" onclick="location.href = '?'">Clear</button>
            <button type="submit">Hitung</button>
        </div>
    </form>
</body>
</html>

Setelah kita coba jalankan, kira-kira beginilah tampilan yang kita dapatkan:

Memproses Form Kalkulator Scientific

Lanjut, setelah form beres dibuat. Kita tambahkan aksi ketika tombol Hitung diklik.

Kita akan menggunakan fungsi eval(). Ia adalah sebuah fungsi yang bertugas untuk mengeksekusi perintah program PHP yang disimpan dalam tipe data string.

Dan ia adalah fungsi yang sangat berbahaya, karena fungsi tersebut memungkinkan user untuk mengeksekusi kode program apa pun jika tidak kita beri pengamanan.

Sehingga, fungsi eval() jangan sekali-kali kita pakai di project beneran, ya! Di sini kita hanya bereksperimen saja.

Langsung saja, dibawah tag </form>, tambahkan kode program berikut:

<?php
if ($_GET):
    $ekspresi = @$_GET['ekspresi'];
    $hasil = eval("return {$ekspresi};"); ?>
    <div style="margin-top: 1rem">
        Hasil <strong><?php echo $hasil ?></strong>
    </div>
    <?php
endif; ?>

Jika kita perhatikan kode program di atas, jumlah barisnya jauh lebih sedikit. Karena di sini kita langsung memasukkan apa yang user inputkan ke dalam fungsi eval(). Dan fungsi tersebut akan mengembalikan nilai dari ekspresi yang user masukkan.

Ketika kita coba inputkan ekspresi matematika semisal: 35 + 100 * (9 / 3). Kita bisa langsung mendapatkan hasilnya:

Canggih bukan?

Kode Program Lengkap

Untuk kode program tutorial ini, bisa kalian akses pada link github berikut: https://github.com/jagongoding-com/php-web-dinamis/tree/master/02-kalkulator.

Pembahasan Selanjutnya

Dengan mempraktikkan tutorial ini, kita bisa mendapatkan gambaran yang lebih jelas lagi tentang bagaimana membuat dan menangani sebuah form dalam PHP.

Akan tetapi, masih ada pembahasan yang kurang: yaitu tentang validasi form. Kenapa sebuah form butuh divalidasi? Karena kita tidak tahu apa yang akan user inputkan! User bisa menginputkan data apa pun yang tidak pernah kita bayangkan, bahkan situs kita bisa diretas gara-gara inputan berbahaya dari user.

Lalu bagaimana cara melakukan validasi form di PHP? Insyaallah kita akan ambil pembahasannya pada pertemuan yang akan datang.

Tetap ikuti tutorial ini, ya! Jangan lupa share dan kabarkan ke teman-temanmu. Terima kasih banyak.


3. Validasi Data 1

PHP: Validasi Data Form [1/3]

Pada 2 pertemuan sebelumnya kita telah membahas tentang membuat form, menangani, dan memproses data yang dikirimkan melalui Form. Bahkan kita telah mencoba membuat kalkulator biasa dan kalkulator scientific sederhana.

Kali ini, kita akan mempelajari tentang validasi data pada Form dan kita juga akan mempraktikkannya secara langsung.

Tutorial tentang validasi form di PHP ini akan dibagi menjadi 3 bagian:

  • Bagian pertama tentang pondasi dasar validasi
  • Bagian kedua implementasi semua jenis validasi yang dibutuhkan
  • Dan bagian ketiga adalah menampilkan pesan error dari validasi yang sudah dibuat

Berikut ini adalah hasil akhir dari tutorial yang akan kita buat:

Kenapa Data Harus Divalidasi?

Jawabannya: karena data yang diinput oleh user itu bisa apa saja. Bisa benar, bisa salah. Bisa data biasa-biasa aja, bisa data yang berbahaya yang justru akan menjadi backdoor untuk aplikasi web yang kita bangun.

Sehingga, data yang diinput harus kita periksa apakah valid atau tidak. Apakah aman atau tidak.

Jenis Validasi Form

Secara umum, terdapat dua buah jenis validasi.

  • Validasi di client: yaitu validasi yang selesai di perangkat client. Untuk web, maka validasi ini selesai di browser (entah menggunakan javascript, atau pun menggunakan atribut HTML5)
  • Validasi di server: yaitu validasi yang selesai di server. Validasi ini adalah validasi yang wajib karena ia adalah pintu gerbang terakhir sebelum data benar-benar diolah.

Apakah kita wajib menggunakan dua jenis validasi tersebut?

Tidak wajib. Yang wajib hanyalah validasi di sisi server. Karena jika validasi hanya terjadi di client saja, itu masih bisa dibobol dengan mudah. Sedangkan di server, ia relatif lebih aman.

Akan tetapi tetap saja cara yang direkomendasikan adalah kita menerapkan dua lapis validasi, baik di client mau pun di server. Hal tersebut agar membuat pengalaman pengguna menjadi lebih baik.

Validasi Form Dengan HTML

Untuk validasi di sisi client, kita bisa memanfaatkan fitur dasar dari HTML. Misalkan dengan menambahkan atribut required pada tag <input><select> mau pun <textarea>.

Contoh:

<form>
  <input type="email" placeholder="Email" required>
  <input type="password" placeholder="Password" required>
  
  <button type="submit">Login</button>
</form>

Jika kita coba jalankan sintaks di atas, lalu kita submit form tanpa mengisi field email dan password, akan muncul peringatan di browser yang kita gunakan bahwa 2 field tersebut wajib diisi.

Kita juga bisa menggunakan atribut type dengan benar sesuai tipe yang tersedia.

Misalkan untuk mendeteksi format email, kita harusnya menggunakan type="email" dari pada type="text". Karena dengan begitu, browser akan memberikan alert jika format email yang kita inputkan tidak sesuai.

Persiapan

Sebelum memulai belajar membuat validasi form sederhana dengan PHP, kita siapkan terlebih dahulu 3 buah file sebagaimana berikut:

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

Dari nama 3 buah file di atas, kita bisa dengan mudah langsung mengetahui tugas dari masing-masing file. Berikut adalah rincian globalnya:

  • file form.php kita gunakan untuk menampilkan form HTML.
  • file proses.php bertugas sebagai action di mana data form akan diproses.
  • dan file helper/fungsi-validasi.php adalah file di mana kita akan meletakkan fungsi-fungsi yang berkaitan dengan validasi data.

Buat Form HTML

Langsung saja. Setelah membuat 3 buah file di atas, kita akan mulai aksi menulis kode program. File pertama yang akan kita buat adalah file form.php, di sana kita akan menampilkan sebuah form HTML.

Buka file form.php lalu isi dengan kode program berikut:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Validasi Form</title>
</head>
<body>
    <h1>Validasi Form</h1>
    <form action="proses.php">
        <div>
            <label>Nama</label> <br>
            <input type="text" name="nama" placeholder="Masukkan nama">
        </div>
        <div style="margin-top: 0.5rem">
            <label>Email</label> <br>
            <input type="email" name="email" placeholder="Masukkan email">
        </div>
        <div style="margin-top: 0.5rem">
            <label>Username</label> <br>
            <input type="text" name="username" placeholder="Masukkan username">
        </div>
        <div style="margin-top: 0.5rem">
            <label>Usia</label> <br>
            <input type="number" name="usia" placeholder="Masukkan usia">
        </div>
        <div style="margin-top: 0.5rem">
            <label>Website</label> <br>
            <input type="url" name="website" placeholder="Masukkan website">
        </div>

        <div style="margin-top: 0.5rem">
            <button>Submit</button>
        </div>
    </form>
</body>
</html>

Berikut ini adalah tampilan yang kita dapatkan:

Buat Fungsi Validasi

Setelah membuat form, kita akan membuat pondasi untuk fungsi validasi form.

Buka file proses.php lalu tulis kode program berikut:

<?php

require_once './helper/fungsi-validasi.php';

$peraturan = [
    'nama' => ['required'],
    'email' => ['required'],
    'username' => ['required'],
    'usia' => ['required'],
    'website' => ['required']
];

validasi($peraturan);

Catatan:

Penjelasan:

  • Variabel $peraturan adalah array asosiatif multidimensi. Yang menjadi key dari variabel ini adalah nama input pada Form PHP
  • Tiap nilai pada array $peraturan adalah array juga, array tersebut berisi tentang peraturan yang kita inginkan.
  • Di sini kita buat peraturan dengan nama required (nama bisa bebas) yang nantinya akan menandakan bahwa field input yang bersangkutan harus diisi.
  • Kita memanggil fungsi validasi() dengan melempar variabel $peraturan sebagai parameter.
  • Fungsi validasi() akan kita tulis pada file helper/fungsi-validasi.php.

Setelah selesai dengan file proses.php. Kita lanjutkan untuk membuat fungsi validasi().

Langsung saja, buka file helper/fungsi-validasi.php lalu tulis kode program berikut:

<?php

function validasi(array $listInput)
{
    # variabel berisi inputan baik dari metode POST mau pun GET
    $request = $_REQUEST;

    # perulangan untuk array terluar (berisi nama input)
    foreach ($listInput as $input => $listPeraturan) {
        echo "Periksa input <strong>{$input}</strong><br>";

        # perulangan untuk sub array (berisi nama peraturan)
        foreach ($listPeraturan as $peraturan) {
            echo "-> Peraturan <strong>{$peraturan}</strong>";

            # pemeriksaan tiap peraturan akan kita lakukan di sini

            echo "<br>";
        }

        echo "<br>";
    }
}

Penjelasan:

  • Kita membuat variabel $request yang berisi sama persis dengan variabel global PHP $_REQUEST.
  • Variabel tersebut berisi input data yang datang dari request client, baik dari metode GET mau pun metode POST.
  • Setelah itu kita membuat perulangan foreach untuk isi pertama dari array $listInput.
  • Di dalam foreach tersebut, kita membuat foreach baru untuk melakukan perulangan list peraturan pada tiap input.

Jika kita menjalankan program PHP kita, lalu menekan tombol submit, kita akan mendapatkan output kira-kira seperti ini:

Mulai Memeriksa Peraturan

Kita berhasil melakukan perulangan untuk variabel yang dilempar kedalam fungsi validasi().

Masih di file helper/fungsi-validasi.php, buat fungsi baru dengan nama lolosRequired().

<?php

function lolosRequired($nilai)
{
    return (bool) @$nilai;
}

Penjelasan

  • Di sini kita akan memeriksa apakah variabel $nilai akan bernilai true jika kita konversi menjadi boolean. Pastikan anda telah mempelajari pembahasan return function dan juga variabel casting.

Setelah membuat fungsi lolsoRequired, tambahkan kode program yang di-highlight berikut tepat pada komentar # pemeriksaan tiap peraturan akan kita lakukan di sini:

<?php

function validasi(array $listInput)
{
    ...
    foreach ($listInput as $input => $listPeraturan) {
        ...
        foreach ($listPeraturan as $peraturan) {
            ...
            if ($peraturan === 'required') {
                $lolos = lolosRequired($request[$input]);

                echo $lolos ? "Lolos" : "Tidak Lolos";
            }
            ...
        }
        ...
    }
}

Penjelasan

  • Kita akan memanggil fungsi lolosRequired() jika variabel $peraturan adalah string bernilai required.
  • Parameter yang kita lempar adalah $request[$input] yang itu adalah nilai dari masing-masing input HTML. Jika perulangan yang aktif sedang memeriksa input dengan name email, maka nilai input email tersebut yang kita kirimkan.
  • Kita akan menampilkan teks “Lolos” atau “Tidak Lolos” berdasarkan nilai dari variabel $lolos. Pastikan anda telah memahami pembahasan tentang kode program percabangan ternary pada PHP.

Eksekusi

Setelah menulis kode program berdasarkan langkah-langkah di atas. Kita bisa mulai mencoba mengeksekusi dan memeriksa apakah kode yang kita buat telah berfungsi dengan baik.

Silakan anda coba untuk mengisi beberapa inputan form, dan membiarkan kosong beberapa inputan lainnya. Lalu klik tombol Submit.

Anda akan mendapatkan output kira-kira sebagai berikut:

Kode Program Lengkap

Untuk melihat kode program validasi form part 1 ini, anda bisa mengunjungi link github berikut: https://github.com/jagongoding-com/php-web-dinamis/tree/validasi-form-part-1/03-validasi-form.

Pembahasan Selanjutnya

Pada pembahasan selanjutnya, insyaallah kita akan mulai membuat peraturan validasi yang lain mulai dari:

  • peraturan validasi angka numerik
  • peraturan validasi email
  • peraturan validasi url
  • peraturan validasi username

Jangan lupa untuk share tulisan ini ke teman-teman mu, ya! Terima kasih banyak.


4. Validasi Data 2

PHP: Validasi Data Form [2/3]

Kita masih berada pada pembahasan validasi form. Pertemuan kali ini adalah pembahasan bagian 2 dari pembahasan tentang validasi form.

Pada pertemuan sebelumnya, kita telah membuat pondasi validasi form:

  • Mulai dari menampilkan form.
  • Membuat fungsi validasi() beserta membuat peraturannya.
  • Kita juga telah membuat pemeriksaan untuk satu aturan validasi yang kita namakan required.

Pada pertemuan kali ini, kita akan melengkapi proses pemeriksaan untuk:

  • Peraturan format email.
  • Peraturan format username.
  • Peraturan angka numerik.
  • Dan peraturan penulisan format url web.

Menambahkan Beberapa Peraturan

Langsung saja, kita mulai dari file proses.php. Pada pertemuan sebelumnya kita telah menambahkan peraturan “required” pada setiap input. Sekarang, kita akan menambahkan beberapa peraturan lain seperti: emailusernamenumeric dan url.

Ubah variabel $peraturan pada file proses.php menjadi seperti berikut:

<?php

require_once './helper/fungsi-validasi.php';

$peraturan = [
    'nama' => ['required'],
    'email' => ['required', 'email'],
    'username' => ['required', 'username'],
    'usia' => ['required', 'numeric'],
    'website' => ['required', 'url']
];

validasi($peraturan);

Selanjutnya kita akan membuat fungsi untuk memeriksa setiap peraturan baru yang telah kita buat.

Validasi Email

Yang pertama adalah fungsi untuk memeriksa email. Untuk memeriksa email, kita akan membuat fungsi bernama lolosEmail() di dalam file helper/fungsi-validasi.php.

<?php

function lolosEmail($nilai)
{
    return filter_var($nilai, FILTER_VALIDATE_EMAIL);
}

Penjelasan:

  • Di sini untuk memeriksa valid tidaknya sebuah email, kita menggunakan fungsi bawaan PHP dengan nama filter_var().
  • Kita sebenarnya juga bisa menggunakan regex yang pernah kita pelajari pada pembahasan: bekerja dengan regex pada PHP.
  • Akan tetapi, tentu saja menggunakan fungsi bawaan PHP jauh lebih convidence.

Panggil fungsi lolosEmail()

Masih dalam file yang sama, sekarang kita akan memanggil fungsi lolosEmail().

Kapan fungsi ini dipanggil?

Fungsi ini akan dipanggil ketika peraturan yang sedang kita periksa sama dengan “email”.

Pada foreach() kedua di dalam fungsi validasi(), tambahkan blok elseif berikut:

<?php
...
if ($peraturan === 'required') {
    ...
} elseif ($peraturan === 'email') {
    $lolos = lolosEmail($request[$input]);

    echo $lolos ? "Lolos" : "Tidak Lolos";
}
...

Dan agar kita bisa melakukan tes validasi server dengan baik, untuk sementara kita ubah dulu type="email" pada file form.php menjadi type="text".

Dengan seperti itu, kita bisa memasukkan input non-email dan tidak diganggu oleh validasi yang dilakukan oleh browser.

<div style="margin-top: 0.5rem">
    <label>Email</label> <br>
    <input type="text" name="email" placeholder="Masukkan email">
</div>

Validasi Username

Validasi selanjutnya adalah validasi username. Prosesnya sama saja seperti sebelumnya: kita buat fungsi lolosUsername() lalu memanggilnya dari dalam foreach.

Untuk fungsi lolosUsername(), kita akan memanfaat regex:

<?php

function lolosUsername($nilai)
{
    preg_match("/^[a-zA-Z0-9_]+/", $nilai, $output);

    if (count($output)) {
        return $output[0] === $nilai;
    }

    return false;
}

Penjelasan:

Untuk memahami regex lebih lanjut, anda bisa pergi ke tutorial PHP tingkat menengah tentang bekerja dengan regex pada PHP.

Memanggil fungsi lolosUsername()

Sama seperti sebelumnya, kita akan memanggil fungsi lolosUsername() ketika variabel $peraturan pada foreach() ke-2 di fungsi validasi() bernilai string “username”.

<?php
...
if ($peraturan === 'required') {
    ...
} elseif ($peraturan === 'email') {
    ...
} elseif ($peraturan === 'username') {
    $lolos = lolosUsername($request[$input]);

    echo $lolos ? "Lolos" : "Tidak Lolos";
}
...

Validasi Angka Numeric

Selanjutnya adalah validasi angka numerik.

Kita buat fungsi bernama lolosNumeric(). Dan fungsi ini sederhana sekali, ia hanya memanggil fungsi bawaan PHP yang bernama is_numeric().

<?php

function lolosNumeric($nilai)
{
    return is_numeric($nilai);
}

Seperti sebelumnya, langkah selanjutnya adalah memanggil fungsi lolosNumeric() jika variabel $peraturan sama dengan “numeric”.

<?php
...
if ($peraturan === 'required') {
    ...
} elseif ($peraturan === 'email') {
    ...
} elseif ($peraturan === 'username') {
    ...
} elseif ($peraturan === 'numeric') {
    $lolos = lolosNumeric($request[$input]);

    echo $lolos ? "Lolos" : "Tidak Lolos";
}
...

Yang terakhir, untuk menguji validasi server: apakah ia sudah bekerja dengan baik atau tidak. Sementara kita ganti dulu nilai type="numeric" menjadi type="text".

<div style="margin-top: 0.5rem">
    <label>Usia</label> <br>
    <input type="text" name="usia" placeholder="Masukkan usia">
</div>

Validasi URL Website

Kita ulangi lagi langkah-langkah yang telah kita buat sebelumnya.

Sekarang adalah validasi untuk url website.

Kita buat fungsi bernama lolosUrl() lalu memanggil fungsi filter_var() bawaan PHP untuk memvalidasi apakah suatu string adalah sebuah url yang valid atau tidak.

<?php

function lolosUrl($nilai)
{
    return filter_var($nilai, FILTER_VALIDATE_URL);
}

NB: kita tetap bisa menggunakan regex. Akan tetapi dengan cara di atas, kode lebih mudah terbaca dan rasanya lebih convidence karena kita menggunakan fungsi native PHP.

Langkah selanjutnya, panggil fungsi lolosUrl() ketika variabel $peraturan bernilai “url”.

<?php
...
if ($peraturan === 'required') {
    ...
} elseif ($peraturan === 'email') {
    ...
} elseif ($peraturan === 'username') {
    ...
} elseif ($peraturan === 'numeric') {
    ...
} elseif ($peraturan === 'url') {
    $lolos = lolosUrl($request[$input]);

    echo $lolos ? "Lolos" : "Tidak Lolos";
}
...

Yang terakhir, seperti yang sudah-sudah: kita ubah dulu sementara type="url" menjadi type="text" untuk memudahkan kita menguji fungsi validasi yang sudah kita buat di dalam PHP.

<div style="margin-top: 0.5rem">
    <label>Website</label> <br>
    <input type="text" name="website" placeholder="Masukkan website">
</div>

Eksekusi

Sampai sini, semua peraturan validasi telah terimplementasi. Kita bisa mulai memeriksa satu-persatu peraturan yang sudah kita tulis.

Ketika kita coba isi data-data yang terdapat pada form, kita akan mendapatkan output yang kira-kira seperti ini:

Kita lihat, setiap peraturan dari setiap input di atas telah berhasil tereksekusi dengan baik. Setiap peraturan yang lolos validasi, akan mengeluarkan output “Lolos”, dan jika tidak, sistem akan mengeluarkan output tulisan “Tidak Lolos”.

Kode Program Lengkap

Kode program lengkap untuk validasi form PHP part 2 ini bisa kalian dapatkan dalam repositori PHP Web Dinamis pada branch validasi-form-part-2.

Pembahasan Selanjutnya

Pada pembahasan selanjutnya, insyaallah kita akan mulai menampilkan pesan error pada form yang telah kita buat. Kita juga akan mempersingkat kode program untuk validasi, dan juga akan menampilkan nilai form terakhir yang telah dikirim ke file proses.php.

Ikuti terus tutorial PHP di Jago Ngoding, jangan lupa share ke teman-teman kalian, ya!

Terima kasih banyak.


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.


6. Upload File

PHP: Belajar Upload File

Dalam lanjutan tutorial PHP web dinamis kali ini, kita akan mulai mempelajari sesuatu yang penting lagi seru. Sesuatu yang pasti ada dalam kebanyakan sistem web yang kita buat. Apa itu? Upload file.

Dalam seri tutorial PHP menengah beberapa waktu lalu, kita telah mempelajari tentang manipulasi file dengan PHP. Dan materi yang akan kita pelajari sekarang ini, masih termasuk salah satu bagian dari manipulasi file.

Hanya saja, dalam pertemuan kali ini kita akan mengambil pembahasan sederhana tentang upload file. Dan insyaallah pada pertemuan-pertemuan berikutnya kita akan membahas lebih dalam tentang variasi upload file dan juga cara pengamanannya.

Persiapan File

Langsung saja.

Siapkan kopi kalian, jangan lupa diseduh.

Lalu buka teks editor favorit. Dan buat projek baru dengan struktur file sebagai berikut:

upload-file/
├── form.html
└── proses.php

Biasanya kita membuat form dengan ekstensi .php. Tapi agar tidak dikira bahwa halaman form wajib berekstensi .php, di sini kita akan gunakan ektensi .html terlebih dahulu.

Membuat Form

Untuk form yang akan kita buat, sederhana saja. Hanya terdiri dari satu buah input file, dan satu buah tombol upload.

Silakan tuliskan kode program berikut:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Upload File</title>
</head>
<body>
    <h1>Belajar Upload File</h1>

    <form action="proses.php" method="POST" enctype="multipart/form-data">
        <div>
            <label>Foto</label> <br>
            <input type="file" name="foto">
        </div>
        <div style="margin-top: 1rem">
            <button>Upload</button>
        </div>
    </form>
</body>
</html>

Penjelasan:

  • Form upload (html) harus menggunakan method POST
  • Data yang dikirim harus dienkripsi dengan metode multipart/form-data. Yang artinya bahwa data yang berisi form tersebut akan dipecah menjadi beberapa bagian (multipart), untuk kemudian dikirimkan ke server [1].
  • Atribut action pada tag <form> di atas mengarah ke file proses.php. Penampakan form.html:

Penampakan file form.html:

Memahami Struktur Data

Sebelum kita mulai proses upload. Kita harus memahami dulu bagaimana “bentuk” data file dikirimkan dari form HTML ke dalam server (dalam hal ini yang menangani sisi server adalah PHP).

Untuk itu, tambahkan kode program berikut pada file proses.php:

<?php

$files = $_FILES;

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

Jalankan form.html, pilih salah satu file gambar. Lalu klik tombol Upload.

Jika tidak terjadi error apa pun, anda akan mendapatkan output kira-kira sebagai berikut:

Array
(
    [foto] => Array
        (
            [name] => foto-ku-3x4.png
            [type] => image/png
            [tmp_name] => /tmp/phpuwTh9e
            [error] => 0
            [size] => 70476
        )

)

Penjelasan

Jika kita melihat isi dari variabel $_FILES, kita akan dapatkan kesimpulan:

  • Bahwa variabel $_FILES merupakan sebuah array asosiatif
  • Setiap file yang dikirim dari HTML form akan menjadi item dari array $_FILES
  • Setiap item tersebut menyimpan beberapa informasi seperti name untuk nama file, type untuk tipe dari file yang diupload, tmp_name lokasi sementara dari file yang diupload, error jika bernilai 0 berarti tidak ada error, dan juga atribut size yang berarti ukuran gambar dalam satuan bytes.

Coba Tambahkan Field Baru

Untuk lebih memahami struktur data dari variabel $_FILES, kita akan menambahkan satu buah inputan file sekali lagi.

Kita input yang baru ini akan kita beri nama sebagai ktp.

Langsung saja, tambahkan kode programnya:

<div style="margin-top: 1rem">
    <label>Berkas KTP</label> <br>
    <input type="file" name="ktp">
</div>

Setelah itu jalankan lagi file form.html, coba upload dua buah file untuk masing-masing field input.

Klik tombol Upload, anda akan mendapatkan output dari variabel $_FILES kira-kira sebagai berikut:

Array
(
    [foto] => Array
        (
            [name] => foto-3x4.webp
            [type] => image/webp
            [tmp_name] => /tmp/phpdUVqae
            [error] => 0
            [size] => 23150
        )

    [ktp] => Array
        (
            [name] => scan-ktp.jpeg
            [type] => image/jpeg
            [tmp_name] => /tmp/phpYF9t7e
            [error] => 0
            [size] => 34794
        )

)

Sampai sini, kita sudah memiliki gambaran yang cukup jelas tentang struktur data sederhana dari variabel $_FILES.

Kita akan melanjutkan ke tahap berikutnya yaitu upload file.

Sebenarnya File Sudah Otomatis Terupload

Iya, sebenarnya tanpa melakukan proses apa pun: file sudah terupload. Karena ketika form.html di-submit, browser akan mengirimkan file tersebut untuk diterima oleh server.

Nah, proses pengiriman seperti ini: itu dinamakan upload.

Akan tetapi, file yang terkirim tersebut tidak langsung masuk ke dalam direktori file projek kita.

Lalu di mana ia disimpan?

Ia disimpan di dalam direktori sementara. Dan lokasi sementara dari file tersebut disimpan dalam nilai tmp_name pada tiap file.

Lalu bagaimana agar file tersebut bisa berada di dalam direktori projek?

Gampang, tinggal kita pindah aja file-nya dari direktori sementara, ke direktori projek kita.

Memindahkan File Yang Terupload

Untuk memindahkannya, kita akan menggunakan fungsi bawaan PHP bernama move_uploaded_file(). Fungsi tersebut menerima 2 buah parameter:

  • Parameter pertama adalah lokasi sementara dari file yang dikirim.
  • Dan yang kedua adalah lokasi dimana file tersebut akan dipindahkan.

Hapus Semua Kode

Sebelum kita mulai, kita hapus dulu semua baris program dari file proses.php.

Buat Direktori Upload

Lalu (pada file yang sama), tambahkan kode program berikut:

<?php

$folderUpload = "./assets/uploads";

# periksa apakah folder sudah ada
if (!is_dir($folderUpload)) {
    # jika tidak maka folder harus dibuat terlebih dahulu
    mkdir($folderUpload, 0777, $rekursif = true);
}

Penjelasan:

  • Kode program di atas bertujuan untuk membuat direktori baru dengan nama /assets/uploads/
  • Lokasi tersebut nantinya akan kita gunakan sebagai tujuan pemberhentian akhir dari file yang kita upload

Simpan Masing-Masing File Ke Dalam Variabel

Pada baris selanjutnya, tambahkan kode program berikut:

<?php

...

# simpan masing-masing file ke dalam array 
# dan casting menjadi objek 😎
$fileFoto = (object) @$_FILES['foto'];
$fileKtp = (object) @$_FILES['ktp'];

Penjelasan:

  • Kita akan menyimpan masing-masing file dari file foto mau pun ktp dalam sebuah variabel terpisah.
  • Kita konversi tipe data array asosiatif masing-masing file menjadi tipe data object alias instant dari stdClass.
  • Apakah wajib dikonversi menjadi objek? Tidak. Tidak wajib. Kita tetap bisa menggunakan tipe data aslinya yaitu array. Saya mengkonversinya ke dalam objek hanya karena saya lebih suka menggunakan tanda panah -> dari pada tanda kurung siku [] untuk mengakses data 😎

Mulai Memindahkan File

Jika semuanya sudah beres, kita bisa langsung memindahkan dua file di atas seperti berikut:

<?php

...

# mulai upload file
$uploadFotoSukses = move_uploaded_file(
    $fileFoto->tmp_name, "{$folderUpload}/{$fileFoto->name}"
);

$uploadKtpSukses = move_uploaded_file(
    $fileKtp->tmp_name, "{$folderUpload}/{$fileKtp->name}"
);

Jika kita periksa file manager dan tidak terjadi error, dua file tersebut harusnya sudah berhasil terupload.

Link dari file yang terupload adalah gabungan dari nama folder upload dan nama file tujuan. Kira-kira seperti ini:

<?php

...

if ($uploadFotoSukses) {
    $link = "{$folderUpload}/{$fileFoto->name}";
    echo "Sukses Upload Foto: <a href='{$link}'>{$fileFoto->name}</a>";
    echo "<br>";
}

if ($uploadKtpSukses) {
    $link = "{$folderUpload}/{$fileKtp->name}";
    echo "Sukses Upload KTP: <a href='{$link}'>{$fileKtp->name}</a>";
    echo "<br>";
}

Validasi Ukuran Maksimal File

Oiya, sebelum proses pemindahan file. Kita juga bisa melakukan beberapa validasi. Seperti misalnya: validasi ukuran maksimum file.

Kita bisa memanfaatkan attribut size pada tiap file untuk melakukannya, contohnya adalah seperti berikut:

<?php

if ($fileFoto->size > 1000 * 2000) {
    die("File tidak boleh lebih dari 2MB");
}

Validasi Tipe File

Atau kita juga bisa memanfaatkan atribut type pada file yang terupload untuk memvalidasi tipe dari file yang bersangkutan:

<?php

if ($fileKtp->type !== 'image/jpeg') {
    die("File ktp harus jpeg!");
}

Akan tetapi, atribut type pada file upload masih rentan untuk dimanipulasi. Bisa jadi file yang sebenarnya bertipe data gambar, ternyata itu adalah sebuah malware yang berbahaya.

Oleh karena itu, cara teraman untuk memeriksa tipe dari suatu file adalah: dengan memeriksa mime type-nya. Insyaallah nanti akan kita bahas hal ini pada kesempatan yang lainnya.

Kesimpulan

Upload file di-PHP tidak lah susah. Sangat sederhana. Kita hanya membuat form, mengatur method menjadi POST, mengatur enctype menjadi multipart/form-data. Lalu browser lah yang akan mengupload file tersebut ke dalam server.

Hanya saja, file yang terupload tersebut, tidak otomatis berada pada direktori yang kita inginkan. Melainkan masih disimpan pada direktori sementara atau temporary directory, untuk kemudian kita simpan pada lokasi yang kita inginkan menggunakan fungsi move_uploaded_file().

Kode Program Lengkap

Untuk kode program lengkap, anda bisa dapatkan di repository PHP Web Dinamis pada akun github jagongoding.

Pembahasan Selanjutnya

Karena pembahasan sudah terlalu panjang, kita sudahi dulu pertemuan ini sampai di sini.

Pada pertemuan selanjutnya, insyaallah kita akan membahas tentang bagaimana cara mengupload multiple files dengan satu input sekaligus.

Jangan lupa share tutorial ini ke teman-teman kalian, ya! Terima kasih banyak.

Referensi

[1] https://stackoverflow.com/questions/4526273/what-does-enctype-multipart-form-data-mean - diakses 18 April 2020



7. Upload Multiple Files

PHP: Upload Multiple Files

Pada pertemuan sebelumnya, kita telah mempelajari cara upload file dengan php.

Kalau kita buka-buka lagi projek yang sebelumnya, kita pada akhirnya memang membuat form yang mengupload dua buah gambar, yaitu gambar untuk foto dan gambar untuk ktp.

Terus? Bukannya itu lebih dari satu file? Berarti multiple files dong?

Enggak juga. Itu tetep single file. Alias satu <input type="file"> hanya untuk satu file. Sedangkan upload multiple files itu, satu input-an bisa untuk lebih dari satu file, dengan cara:

  1. Menambahkan atribut multiple pada tag <input> dan dengan
  2. Dan mengubah name menjadi array, seperti ini:
<input
    type="file"
    name="listGambar[]"
    accept="image/*"
    multiple>

Pada kode html di atas, tag input memiliki:

  1. Name listGambar[] yang berupa array (karena ada tanda kurung siku [])
  2. Atribut multiple, yang memungkinkan user untuk memilih lebih dari satu file secara sekaligus.

Persiapan File

Langsung saja. Kita buat project-nya.

Kemudian buat dua file dengan struktur berikut:

upload-file/
├── form.html
└── proses.php

File form.html sebagai form-nya, dan file proses.php untuk menangani proses upload-nya.

Oiya, jangan lupa bikin ☕ dulu, ya! 😁

Membuat Form HTML

Selanjutnya kita buka file form.html, lalu tulis kode program seperti berikut:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Upload Multiple Files PHP | Jago Ngoding</title>
</head>
<body>
    <h1>Upload Multiple Files PHP | Jago Ngoding</h1>
    <form action="proses.php" method="POST" enctype="multipart/form-data">
        <div>
            <label>Pilih gambar</label> <br>
            <input type="file" name="listGambar[]" accept="image/*" multiple>
        </div>

        <button style="margin-top: 2rem">Upload</button>
    </form>
</body>
</html>

Hal yang paling penting adalah:

  1. Nama dari input file harus berupa array (yaitu dengan menambahkan kurung siku [])
  2. Lalu menambahkan atribut multiple pada input file agar ia bisa menerima lebih dari satu file secara sekaligus.
  3. Sisanya kurang lebih sama seperti pertemuan sebelumnya tentang upload single file.

Bentuk Data yang Dikirim Untuk Multiple Files

Seperti biasa, sebelum kita mulai proses upload file.

Kita akan terlebih dahulu membedah isi dari variabel super global $_FILES untuk kasus upload multiple files.

Pada file proses.php, tuliskan kode program berikut:

<?php

$files = $_FILES;

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

Nantinya kode program di atas akan kita hapus.

1. Pilih Files

Langsung kita test drive.

  1. Klik tombol Choose Files (jika bahasa inggris)

  2. Lalu pilih lebih dari satu gambar dengan menekan tombol Ctrl atau Shift

    Pada contoh ini saya memilih 2 buah file:

  3. Setelah itu, akan ada informasi untuk berapa jumlah file yang telah kita pilih.

2. Submit

Langsung saja klik tombol Upload.

Kita akan mendapatkan hasil (kira-kira) seperti berikut:

Penjelasan

  1. Pada variabel $_FILES, terdapat indeks dengan nama listGambar dengan tipe data array asosiatif.
  2. $_FILES['listGambar'] bertipe data array (asosiatif) dengan atribut:
    1. name - berisi informasi nama file
    2. type - berisi informasi tipe file
    3. tmp_name - berisi informasi lokasi tmp file pada server
    4. error - berisi informasi tentang error upload
    5. size - berisi informasi tentang ukuran file
  3. Setiap atribut dari $_FILES['listGambar'] adalah array terindeks. Indeks 0 (pertama) untuk file pertama, dan indeks 1 (kedua) untuk file kedua.

Bikin Direktori assets/uploads

Okay, karena kita telah mengetahui bagaimana wujud struktur datanya, sekarang kita bisa hapus kode program pada file proses.php, lalu menggantinya dengan kode program di bawah:

<?php

$folderUpload = "./assets/uploads";

# periksa apakah folder tersedia
if (!is_dir($folderUpload)) {
    # jika tidak maka folder harus dibuat terlebih dahulu
    mkdir($folderUpload, 0777, $rekursif = true);
}

Penjelasan

Kode program di atas fungsinya sama saja seperti pada pertemuan sebelumnya, yaitu:

  • Untuk memeriksa apakah di dalam direktori projek kita, terdapat direktori assets/uploads atau tidak.
  • Jika tidak, maka kita akan membuat direktori tersebut dengan fungsi mkdir.

Tampilkan Nama File Yang Sudah Dipilih

Setelah itu, kita akan mulai mengupload (atau memindahkan file yang sudah terupload) ke dalam direktori assets/uploads.

Akan tetapi, pertama-tama kita harus tau terlebih dahulu:

  • berapa jumlah file yang terupload?
  • apa nama file yang terupload?
  • apa lokasi sementara (tmp) dari file tersebut?
<?php

...

$files = $_FILES;
$jumlahFile = count($files['listGambar']['name']);

for ($i = 0; $i < $jumlahFile; $i++) {
    $namaFile = $files['listGambar']['name'][$i];
    $lokasiTmp = $files['listGambar']['tmp_name'][$i];

    echo "nama: $namaFile, tmp: {$lokasiTmp} <br>";
}

Penjelasan

Nah, pada kode program di atas, kita telah:

  1. Mengambil jumlah file dengan menghitung length dari array $files['listGambar']['name']. Kita bisa mengganti atribut name dengan yang lain seperti type, atau tmp_name dan hasilnya akan sama saja.
  2. Melakukan perulangan dengan for sebanyak $jumlahFile.
  3. Mengambil nama file dan juga lokasi tmp sesuai dengan indeks perulangan ($i).

Refresh dan kirim ulang file yang telah kita upload, maka kita akan mendapatkan output kira-kira seperti berikut:

Upload File

Karena kita sudah berhasil mendapatkan nama dan juga lokasi tmp, maka yang harus kita lakukan selanjutnya adalah memindah gambar tersebut dari lokasi tmp, ke lokasi baru.

Perhatikan kode program berikut:

<?php

...

for ($i = 0; $i < $jumlahFile; $i++) {
    $namaFile = $files['listGambar']['name'][$i];
    $lokasiTmp = $files['listGambar']['tmp_name'][$i];

    # kita tambahkan uniqid() agar nama gambar bersifat unik
    $namaBaru = uniqid() . '-' . $namaFile;
    $lokasiBaru = "{$folderUpload}/{$namaBaru}";
    $prosesUpload = move_uploaded_file($lokasiTmp, $lokasiBaru);

    # jika proses berhasil
    if ($prosesUpload) {
        echo "Upload file <a href='{$lokasiBaru}' target='_blank'>{$namaBaru}</a> berhasil. <br>";
    } else {
        echo "<span style='color: red'>Upload file {$namaFile} gagal</span> <br>";
    }
}

Coba jalankan kembali program, lalu upload beberapa file.

Jika tidak ada error apa pun, harusnya kita akan mendapatkan output kira-kira seperti berikut:

Kesimpulan

Bagaimana? Mudah sekali bukan? Perbedaan inti dari cara upload single file dengan upload multiple files hanya lah dari sisi sturktur data yang dikirim, dan juga dari atribut serta nama dari input file HTML yang kita buat.

Ada pun sisanya, maka secara umum sama saja.

Kode Program Lengkap

Untuk kode program lengkap, kalian bisa dapatkan di repository PHP Web Dinamis pada akun github jagongoding.

Jangan lupa kasih star ya!⭐🌟

Mengamankan Proses Upload File

Ini adalah contoh upload multiple file yang sangat sederhana. Tanpa validasi, tanpa simpan ke database. Tujuan intinya adalah agar kita paham bagaimana cara kerjanya dari yang paling dasar. Dan agar kita bisa memodifikasinya sendiri sesuai kebutuhan.

Ada pun pada pertemuan selanjutnya, insyaallah kita akan membahas tentang validasi dan cara mengamankan proses upload file pada PHP!

Stay tune!

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


8. Validasi Upload File

PHP: Validasi Upload File

Bismillah.

Pada dua pertemuan terakhir kita telah membahas upload file pada PHP. Baik upload untuk single file maupun upload untuk multiple files.

Tapi, masih ada satu hal yang belum kita bahas.

Apa itu?

Validasi upload file. Validasi yang dimaksud adalah: kita akan memastikan bahwa file yang diupload oleh user adalah benar-benar file yang kita ijinkan. Misal ada form upload foto, maka validasinya akan memastikan bawha:

  1. File yang diupload harus benar-benar foto
  2. Dan ukuran file harus kurang dari batas yang kita tentukan

Kenapa File Upload Harus Divalidasi

Kenapa file harus divalidasi?

Pertanyaan yang menarik.

Jawabannya adalah: karena file upload ini adalah gerbang menuju celah keamanan yang sangat berbahaya terhadap server maupun aplikasi kita.

Langkah pertama yang dilakukan oleh penyerang adalah: berusaha memasukkan kode program “jahat” ke dalam server. Lalu, setelah berhasil, mereka akan berusaha untuk menjalankan kode program “jahat” tersebut [1].

Dan jika fitur upload file di web yang kita bangun tidak kita validasi, ini akan menjadi santapan empuk bagi mereka para penyerang.

Bahkan, menurut statistik yang dipaparkan oleh wordfence, serangan yang diakibatkan oleh file upload ini termasuk nomor 3 yang paling sering terjadi [2].

Lalu, apa yang harus kita lakukan?

Tenang. Kita seduh ☕ dulu agar lebih santuy 😁

Persiapan

Oke, setelah mengetahui pentingnya melakukan validasi untuk file-file yang diupload, kita akan mencoba mempraktikkannya secara langsung.

Ada beberapa jenis validasi yang bisa kita lakukan ketika proses upload file, semisal:

  1. Validasi agar file harus diisi
  2. Validasi ukuran minimal atau maksimal file yang diijinkan
  3. Validasi jenis atau tipe file

Sebelum mulai, siapkan dua buah file seperti berikut:

src/
├── index.html
└── proses.php

Isi dari file index.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Validasi Upload File | Jago Ngoding</title>
</head>
<body>
  <h1>Validasi Upload File | Jago Ngoding</h1>
  <p>
    Belajar 3 jenis validasi untuk file upload.
  </p>
  <form
    action="proses.php"
    method="POST"
    enctype="multipart/form-data">

    <div>
      <label>Foto SIM</label> <br>
      <input type="file" name="foto_sim">
    </div>

    <button style="margin-top: 1rem">Upload</button>
  </form>
</body>
</html>

Kemudian, buat dua buah variabel pada file proses.php seperti berikut:

<?php

/**
 * Simpan file foto yang terupload ke variabel,
 * dan casting menjadi objek untuk memudahkan.
 */
$fileFoto = (object) @$_FILES['foto_sim'];

/**
 * Array ini digunakan untuk menyimpan setiap error yang terjadi.
 * Jika array ini kosong, berarti file yang diupload telah lolos
 * validasi.
 */
$listPesanError = [];

Penjelasan

Penggunaan statemen (object) saat pendeklarasian variabel $fileFoto dinamakan proses casting. Bertujuan agar variabel $_FILES['foto_sim'] yang berupa array akan terkonversi ke dalam bentuk objek. Pembahasannya telah kita lakukan pada tutorial Casting Variabel Pada PHP.

Sedangkan penggunaan @ sebelum mengakses array $_FILES bertujuan agar jika key foto_sim tidak ada, PHP tidak mengembalikan sebuah error, dan menganggtinya dengan nilai null.

Validasi Agar File Harus Diisi

Tetap buka file proses.php.

Kita akan mulai dengan peraturan pertama: yaitu file foto wajib diisi! Tidak boleh kosong!

Untuk memeriksanya, kita akan memanfaatkan atribut name pada variabel $fileFoto. Jika atribut tersebut bernilai null atau dianggap false, artinya file fotonya kosong alias tidak diupload.

Begini kodenya:

<?php

...

/**
 * Peraturan Pertama: file harus diisi
 */
if (!@$fileFoto->name) {
    array_push($listPesanError, "File SIM tidak boleh kosong.");
}

Validasi Untuk Ukuran Maksimal File

Untuk peraturan kedua, kita akan membuat sebuah blok if lagi.

Apa yang akan kita periksa?

Kita akan memeriksa ukuran file. Ia tidak boleh melebihi 1MB (alias 1000 * 1000 byte).


...

/**
 * Peraturan kedua: ukuran minimal file adalah 1MB.
 * 
 * Di sini kita bisa menggunakan elseif dari pada membuat
 * if baru seperti ini.
 */
if ($fileFoto->size > 1000 * 1000) {
    array_push($listPesanError, "Ukuran maksimal file adalah 1MB.");
}

Di sini kita membuat blok if baru.

Itu artinya: jika kondisi if pertama terpenuhi, if yang kedua akan tetap dieksekusi.

Berbeda halnya jika kita membuat blok kode elseif, maka jika kondisi yang pertama terpenuhi, maka kondisi kedua tidak akan dieksekusi.

Tampilkan Pesan Error dan Hentikan Program

Oke. Jangan banyak-banyak. Kita coba 2 rule terlebih dahulu.

Sekarang, kita akan memeriksa variabel $listPesanError apakah ia kosong atau tidak.

Kalau kosong artinya file yang kita upload sudah benar, kalau tidak kosong, berarti ada yang tidak memenuhi peraturan.

Tambahkan kode program di bawah ini:

<?php

...

/**
 * Tampilkan pesan error dan hentikan program jika validasi tidak lolos.
 */
if ($listPesanError) {
    foreach ($listPesanError as $pesanError) {
        echo "<strong style='color: red'>{$pesanError}</strong><br>";
    }

    echo "<a href='index.html'>Kembali</a>";

    # hentikan program
    die();
}

Nah, sekarang saatnya test drive.

Kita coba dua skenario:

  1. Klik tombol Upload tanpa memilih file.
  2. Upload file dengan ukuran lebih dari 1MB.

Untuk skenario pertama, kita akan dapat pesan error sebagai berikut:

Dan untuk skenario kedua, kita akan dapat pesan error seperti ini:

Validasi Jenis File Berdasarkan Ekstensi (Tidak Direkomendasikan)

Oke. Kita rehat dulu sejenak.

Ambil secangkir ☕ yang sudah kita seduh, lalu kita nikmati bersama-sama 😁

Masih mau lanjut?

Oke.

Sekarang kita lanjutkan lagi untuk rule ketiga, yaitu pemeriksaan tipe file.

Ini adalah pemeriksaan yang sangat penting.

Ada dua metode untuk melakukan pemeriksaan tipe file, kita bisa memeriksa berdasarakan ekstensi nama file, dan kita juga bisa memeriksa dari mime type.

Cara yang pertama tidak direkomendasikan karena ekstensi file bisa saja menipu. Kita bisa dengan mudah membuat file malware, lalu memberinya ekstensi .png atau .jpg dan sistem akan mengira bahwa itu adalah file gambar betulan.

Untuk memeriksa tipe file berdasarkan ekstensi, kita bisa mendapatkannya secara langsung dari $_FILES['nama_input']['type']. Contoh tipe-tipe file:

  • image/jpeg
  • image/png
  • video/mp4
  • video/webm
  • dan lain-lain.

Untuk memeriksanya, kita bisa melakukannya sebagai berikut:

<?php
... 

/**
 * Peraturan ketiga: periksa file berdasarkan ekstensi
 */
$ekstensiYangDibolehkan = [
    'image/png',
    'image/jpg',
    'image/jpeg',
    'image/webp'
];

if (!in_array(@$fileFoto->type, $ekstensiYangDibolehkan)) {
    array_push($listPesanError, "Ekstensi file tidak diijinkan.");
}

...

Tes Drive

Saya memiliki file video dengan nama video.webm dan ukuran 1.1MB.

File tersebut tidak memenuhi 2 peraturan:

  • ukuran maksimum 1MB.
  • ekstensi file tidak diijinkan.

Sehingga, jika saya upload, saya dapat pesan:

Rekayasa Ekstensi File

Hmmm…

Karena kita hanya memeriksa tipe file dari nama ekstensinya, itu artinya kita bisa memanipulasinya.

Dengan linux, kita bisa merename ekstensi file secara langsung seperti saat kita mengedit nama.

Kita coba rename video.webm menjadi video.jpg.

Lalu upload ulang.

Apa yang terjadi?

File video tadi lolos pemeriksaan!

Bayangkan jika yang diupload tadi aslinya adalah file php yang berisi malware? Server kita bisa diambil alih oleh penyerang.

Validasi Jenis File Berdasarakan Mime Content Type (Direkomendasikan)

Tenang saja. Untuk memeriksa tipe file yang lebih akurat, kita bisa memeriksanya berdasarkan mime content type.

Caranya gimana?

Kita bisa melakukannya dengan memanggil fungsi mime_content_type(path_file) dan memasukkan $fileFoto->tmp_name sebagai parameternya.

Untuk mencobanya, tambahkan kode program berikut setelah peraturan ketiga:

<?php

...

/**
 * Peraturan keempat: periksa tipe file berdasarkan mime content type
 */
if (!in_array(mime_content_type($fileFoto->tmp_name), $ekstensiYangDibolehkan)) {
    array_push($listPesanError, "Tipe file tidak diijinkan.");
}

...

Nah. Sekarang, file video.jpg saya tetap dianggap sebagai file video meskipun ekstensi pada nama file-nya adalah jpg 😁

Upload File Jika Lolos

Jika tidak ada pesan error apa pun, kita bisa mulai melakukan upload file seperti biasanya.

Kode Program Lengkap

Untuk kode program lengkap (ditambah dengan upload file jika berhasil), kalian bisa mengaksesnya pada repository php-web-dinamis di github.

Jangan lupa kasih ⭐ ya!

Pertemuan Selanjutnya

Insyaallah pada pertemuan berikutnya kita akan membahas session pada PHP.

Stay tune!

Terima kasih banyak.

Referensi

[1] https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload - Diakses pada tanggal 15 Februari 2021
[2] https://www.wordfence.com/learn/how-to-prevent-file-upload-vulnerabilities/ - Diakses pada tanggal 15 Februari 2021