Tag: PHP

  • Validasi dan Sanitasi Form dengan PHP

    Salah satu fitur PHP yang paling penting adalah kemampuannya untuk mengolah form HTML. Form adalah halaman yang hampir dapat dijumpai pada setiap website, contohnya adalah form untuk login, form pendaftaran, form kontak, dll. Mengolah form HTML dengan PHP sangat mudah, dan karena kemudahannya inilah banyak programer yang membuat form secara sembarangan.

    Validasi dan sanitasi data adalah 2 hal yang tidak bisa dilepaskan ketika bekerja dengan form. Data yang tidak valid dan tidak bersih, tidak hanya akan menghasilkan informasi yang salah tetapi juga akan menimbulkan masalah keamanan. Artikel ini akan membahas proses pembuatan form dari yang sederhana sampai yang cukup kompleks dengan validasi dan sanitasi data. Hasil akhir diharapkan mampu meminimalkan kesalahan dan masalah kemananan pada form.

    Contoh 1. Pengolahan form paling sederhana dengan PHP
    nama file: test.html

    <form name="form_test" method="post" action="test.php">
      <p><label for="email">Email </label><input name="email" type="text"/></p>
      <p><label for="website">Website </label><input name="website" type="text" /></p>
      <p><input type="submit" name="submit" value="kirim"></p>
    </form>
    

    nama file: test.php

    <?php
    echo 'Email: ' . $_POST['email'] . '<br />';
    echo 'Website: ' . $_POST['website'];
    

    Pada contoh di atas, tidak ada kode yang memvalidasi dan menyanitasi masukan dari pengguna. Akibatnya apapun data yang dimasukan oleh pengguna akan langsung diproses oleh PHP. Hal ini tidak boleh terjadi. Salah satu masalah yang mungkin terjadi adalah ketika pengguna tidak memasukan data sesuai format dengan benar (baik email maupun website). Sebenarnya HTML5 dapat sedikit membantu tugas para programer, yaitu dengan mengganti nilai type menjadi “email” dan “url“.

    Contoh 2. HTML5 form
    nama file: test.html

    <form name="form_test" method="post" action="test.php">
      <p><label for="email">Email </label><input name="email" type="email"/></p>
      <p><label for="website">Website </label><input name="website" type="url" /></p>
      <p><input type="submit" name="submit" value="kirim"></p>
    </form>
    

    Dengan kode di atas, sekarang akan muncul tooltips ketika pengguna salah memasukan email atau website. Sebagai catatan, belum semua browser mendukung fitur ini, jadi validasi dan sanitasi pada server side (kode PHP) mutlak diperlukan.

    Memeriksa validitas dan membersihkan data dari karakter-karakter yang tidak diinginkan adalah pekerjaan yang tidak mudah. Untungnya, mulai versi 5.2, PHP mempunyai function yang disebut filter_var yang akan membuat pekerjaan programer menjadi jauh lebih mudah. Function filter_var dapat melakukan kedua hal tersebut, baik validasi maupun sanitasi data. Sebenarnya apakah perbedaan di antara keduanya?

    1. Validasi: menentukan apakah sebuah data memiliki format yang valid.
    2. Sanitasi: menghilangkan karakter-karakter yang tidak diinginkan pada sebuah data.

    Mengapa harus keduanya? Karena ada kemungkinan pengguna, baik sengaja maupun tidak sengaja memasukan karakter yang bisa berakibat buruk pada aplikasi. Berikut ini adalah contoh penggunaan filter_var.

    <?php
    $string = "<h1>Hello, World!</h1>";
    $string = filter_var($string, FILTER_SANITIZE_STRING);
    echo 'variabel $string bernilai "' . $string . '"';
    

    Tampak pada contoh kode di atas, filter_var akan menghilangkan semua tag HTML pada suatu string. Sekarang ubah file “test.php” di atas untuk memvalidasi dan menyanitasi masukan email dan website.

    Contoh 3. PHP filter_var
    nama file: test.php

    <?php
    if (!empty($_POST['email'])) {  
      $email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);  
      if (filter_var($email, FILTER_VALIDATE_EMAIL)) {  
        echo "Email $email valid.<br/>";  
      } else {  
        echo "Email $email tidak valid.<br/>";  
      }  
    } else {
      echo "Email harus diisi.<br/>";
    }
    
    if (!empty($_POST['website'])) {  
      $website = filter_var($_POST['website'], FILTER_SANITIZE_URL);  
      if (filter_var($website, FILTER_VALIDATE_URL)) {  
        echo "Website $website valid.";  
      } else {  
        echo "Website $website tidak valid.";  
      }  
    } else {
      echo "Website harus diisi";
    }
    

    Sebagai catatan, alamat website yang valid itu harus mengandung “http://“. Kode !empty($_POST['email']) adalah untuk memeriksa apakah pengguna memasukan data atau tidak.

    Selain dengan filter_var, masih ada cara lain yang bisa digunakan, terutama jika server belum mendukung function ini, yaitu dengan htmlspecialchars. Function htmlspecialchars akan mengkonversi 5 karakter khusus menjadi representasinya dalam bentuk kode. Kelima karakter tersebut beserta representasinya adalah sebagai berikut.

    • &‘ (ampersand) dikonversi menjadi ‘&amp;‘.
    • "‘ (double quote) dikonversi menjadi ‘&quot;‘.
    • '‘ (single quote) dikonversi menjadi ‘&#039;‘.
    • <' (less than) dikonversi menjadi '&lt;'
    • '>' (greater than) dikonversi menjadi '&gt;'

    Contoh penggunaannya adalah sebagai berikut.

    <?php
    $string = htmlspecialchars("<a href='test'>Test string</a>", ENT_QUOTES);
    echo $string; // &lt;a href=&#039;test&#039;&gt;Test string&lt;/a&gt;
    

    Jalankan kode di atas, lalu view source hasilnya. Hasil view source akan sama seperti yang ada pada baris komentar di atas. Pada function htmlspecialchars di atas, terdapat argumen ENT_QUOTES yang berarti akan mengkonversi ''' (single quote) dan '"' (double quote). Jika argumennya ENT_NOQUOTES, kedua quote tidak akan dikonversi.

    sql injection

    Akhirnya, jika bekerja dengan database, dibutuhkan suatu function yang akan melindungi database dari serangan SQL Injection. Function mysql_real_escape_string akan membersihkan semua data yang akan dimasukan ke dalam database.

    <?php
    $email = mysql_real_escape_string($email);
    $website = mysql_real_escape_string($website);
    $query = 'UPDATE nama_tabel SET website = ' . $website . ' WHERE email = ' . $email;  
    mysql_query($query);  
    
  • Autentikasi dan Mengambil Data Pengguna dengan Facebook SDK

    Tutorial ini sudah banyak didokumentasikan di blog-blog baik dalam dan luar negeri, tetapi sangat membingungkan bagi saya. Beberapa tutorial menggunakan JavaScript SDK, sedangkan yang lain menggunakan PHP SDK. Belum lagi, banyak di antaranya yang sudah kadaluarsa dan diperburuk oleh revisi dari Facebook yang tidak menentu.

    Hal lain yang juga membingungkan adalah perbedaan tampilan kotak dialog yang menanyakan izin untuk mengakses data-data. Bandingkan tampilan dialog yang saya ambil dari Facebook Developers Guide berikut dengan yang dihasilkan dari tutorial ini.

    login with facebook

    Sebenarnya hanya ada 2 hal dasar yang menjadi alasan untuk menggunakan Facebook SDK.
    1. Kita mempunyai sistem “register” dan “login” sendiri, dan ingin menambahkan “Login with Facebook” sebagai pilihan bagi pengguna yang malas untuk mendaftar secara normal.
    2. Kita membutuhkan data-data pengguna yang sudah dicatat dengan baik oleh Facebook, tentunya dengan persetujuan pemilik akun.

    Dokumentasi dan kode sumber yang ada di Facebook Developers Guide sudah lengkap, namun susah diikuti dan tidak semuanya saya butuhkan. Tutorial ini akan menggabungkan Javascript SDK dan PHP SDK, karena cara ini menurut saya paling sederhana untuk memenuhi 2 kebutuhan dasar di atas.

    Langkah-langkah untuk menghubungkan website dengan Facebook SDK adalah:
    1. Daftarkan website pada halaman Facebook Developers, di situ akan diperoleh “App ID” dan “App Secret”.
    2. Buat sebuah table pada database untuk menyimpan data-data pengguna dari Facebook. Field-nya sesuai kebutuhan saja, contoh: nama, password, email, tipe (password yang dimaksud di sini bukan password facebook dan tipe akan berisi “facebook” jika data diambil dari facebook dan “normal” jika tidak).
    3. Download Facebook SDK. Ambil semua isi folder “src” (kita hanya membutuhkan ini).
    4. Tombol login bisa menggunakan tag HTML biasa

    <div class="fb-login-button">

    atau menggunakan JavaScript SDK.

    <fb:login-button>

    Dengan ini kita bisa mengakses data-data pengguna yang diatur secara publik (tidak disembunyikan), misalnya id, nama, jenis kelamin. Data-data yang tidak bisa diakses publik harus ditulis ke dalam atribut scope.

    <fb:login-button scope="email, read_stream"></fb:login-button>

    5. Deklarasikan Facebook object di paling atas halaman. Jangan lupa isi “App ID” dan “App secret”. Kemudian ambil data-data pengguna (sudah termasuk yang ditulis di atribut scope tadi) dengan Facebook API.

    require_once("facebook.php");
    
    $config = array();
    $config['appId'] = '';
    $config['secret'] = '';
    
    $facebook = new Facebook($config);
    
    $user = $facebook->getUser();
    
    if ($user) {
      try {
        $user_profile = $facebook->api('/me');
      } catch (FacebookApiException $e) {
        error_log($e);
        $user = null;
      }
    }
    

    6. Terakhir, data-data yang sudah diperoleh dari Facebook API bisa diolah sesuai keinginan. Untuk lebih memahami, baca komentar yang ada pada kode sumber.

    <?php if($user) { ?>
    
    //tampilkan foto dan nama user		      
    <img src="https://graph.facebook.com/<?php echo $user; ?>/picture">
    <?=$user_profile['name']?>
    		    
    <?php
    //ambil data-data yang ingin disimpan
    $fb_id = $user_profile['id'];
    $username = $user_profile['username'];
    $email = $user_profile['email'];
    
    //periksa apakah user sudah pernah login
    $insert = true;
    if (/*query untuk memeriksa apakah data sudah ada di database*/)
        $insert = false;
    
    //jika pertama kali login, masukan data user ke database
    if($insert) {
        /*query INSERT untuk memasukan data ke database*/
    }
    
    //login user
    /* kode untuk login user dan SESSION */
    ?>
    
    <?php } else { ?>
    <fb:login-button scope="email, read_stream"></fb:login-button>
    <?php } ?>
    

    Gabungkan langkah ke-5 dan ke-6 serta tambahkan JavaScript SDK. Akhirnya kita akan memperoleh data dalam bentuk array setelah login dengan Facebook.

    <?php 
    require_once("facebook.php");
    
    $config = array();
    $config['appId'] = 'isi_dengan_app_id';
    $config['secret'] = 'isi_dengan_app_secret';
    
    $facebook = new Facebook($config);
    
    $user = $facebook->getUser();
    
    if ($user) {
      try {
        $user_profile = $facebook->api('/me');
      } catch (FacebookApiException $e) {
        error_log($e);
        $user = null;
      }
    }
    
    if ($user) { ?>
    
    <pre>
    <?php print_r($user_profile) ?>
    </pre>
    
    <?php } else { ?>
    <fb:login-button scope="email, read_stream"></fb:login-button>
    <?php } ?>
    <div id="fb-root"></div>
    
    <script>
    window.fbAsyncInit = function() {
      FB.init({
        appId: '<?php echo $facebook->getAppID() ?>',
        cookie: true,
        xfbml: true,
        oauth: true
      });
      FB.Event.subscribe('auth.login', function(response) {
        window.location.reload();
      });
      FB.Event.subscribe('auth.logout', function(response) {
        window.location.reload();
      });
    };
    (function() {
      var e = document.createElement('script'); e.async = true;
      e.src = document.location.protocol +
        '//connect.facebook.net/en_US/all.js';
      document.getElementById('fb-root').appendChild(e);
    }());
    </script>
    
  • Troubleshooting “Unexpected T_ECHO” pada Operator Ternary

    Satu kesalahan yang kerap dijumpai pada penggunaan operator ternary adalah

    Unexpected T_ECHO

    Pesan kesalahan di atas akan muncul jika pada pernyataan kedua dan ketiga berisi perintah/eksekusi suatu pernyataan. Perhatikan contoh berikut:

    <?php
    $angka = 10;
    $angka % 2 === 0 ? echo "genap" : echo "ganjil";
    

    Pernyataan 2 dan 3 berisi perintah echo yang berfungsi mencetak tulisan “genap”/”ganjil” pada browser. Operator ternary tidak sepenuhnya identik dengan pernyataan if/else. Pada if/else kita dapat mengeksekusi suatu perintah, seperti yang ditunjukkan pada kode berikut:

    <?php
    $angka = 10;
    if ($angka % 2 === 0)
      echo "genap"
    
    else echo "ganjil";
    

    Berbeda dengan if/else, setelah kondisi dievaluasi, operator ternary harus mengembalikan suatu nilai dari pernyataan 2 atau 3. Nilai di sini bisa berupa string, number, atau boolean. Jika masih ingin menggunakan operator ternary, kode di atas harus diubah menjadi sebagai berikut:

    <?php
    $angka = 10;
    echo $angka % 2 === 0 ? "genap" : "ganjil";
    
  • Menyingkat Kode PHP menggunakan Operator Ternary (?:)

    Salah satu konsep dasar pemrograman yang penting adalah pernyataan bersyarat, atau lebih dikenal dengan istilah percabangan. Percabangan adalah suatu kondisi yang dipakai oleh bahasa pemrograman untuk mengatur alur logika program. Dalam bahasa pemrograman PHP setidaknya dikenal 2 macam percabangan, yaitu if/else dan switch/case.

    Percabangan dengan if/else dapat disederhanakan menggunakan operator ternary. Contoh operator ternary bisa dijumpai pada artikel ini, ini, dan ini. Operator ternary memiliki bentuk dasar sebagai berikut:

    (pernyataan1) ? (pernyataan2) : (pernyataan3)

    Bentuk di atas memiliki arti: jika “pernyataan1” adalah benar, nilai kembalian adalah “pernyataan2”, dan jika sebaliknya, nilai kembalian adalah “pernyataan3”. Untuk lebih jelasnya, perhatikan contoh berikut.

    <?php
    $var = 7;
    $cek_var = $var > 5 ? true : false;
    

    Pada contoh di atas nilai variable $cek_var adalah true, karena pernyataan nilai $var lebih besar dari 5 adalah benar. Berikut ini adalah padanannya dalam bentuk if/else.

    <?php
    $var = 7;
    if ($var > 5)
      $cek_var = true;
    
    else
      $cek_var = false;
    

    Contoh aplikasi di dunia nyata adalah seperti yang biasa digunakan untuk memberikan nilai default pada sebuah variable.

    <?php
    $action = !isset($_POST['action']) ? 'default' : $_POST['action'];
    

    Kode di atas identik dengan:

    <?php
    if (!isset($_POST['action'])) {
        $action = 'default';
    } else {
        $action = $_POST['action'];
    }
    

    Bonus:
    Operasi menghitung jumlah hari (termasuk memeriksa tahun kabisat) dalam satu bulan menggunakan operator ternary bertingkat.

    <?php
    $bulan = 2; // bulan Februari
    $tahun = 2012; // ini tahun kabisat
    
    $jumlah_hari = ($bulan == 2 ? ($tahun % 4 ? 28 : ($tahun % 100 ? 29 : ($tahun %400 ? 28 : 29))) : (($bulan - 1) % 7 % 2 ? 30 : 31));
    echo $jumlah_hari;
    
  • Membuat Tombol “Back”

    Pada umumnya browser sudah memiliki tombol “back” yang berfungsi untuk kembali ke halaman sebelumnya. Seorang web developer harus mempunyai alasan yang bagus untuk memasangnya pada website, misal karena adanya permintaan khusus dari klien. Namun, artikel ini ditulis bukan demi klien, melainkan demi ilmu pengetahuan 🙂

    Ada 2 cara yang bisa dipakai, yaitu dengan JavaScript dan PHP. Untuk mencoba kode-kode di bawah ini, dibutuhkan sebuah halaman lain yang berisi link menuju ke halaman yang berisi tombol “back” ini.

    <input type="button" value="Go Back" onclick="history.back(-1)" />
    

    Tentunya implementasi menggunakan JavaScript masih kurang, karena ada kemungkinan user mematikan JavaScript di browser-nya. Berikut ini adalah implementasi dengan PHP.

    <?php
      $url = htmlspecialchars($_SERVER['HTTP_REFERER']);
    ?>
      <a href="<?=$url?>">Go Back</a>
    

    Pada snippet di atas digunakan fungsi PHP htmlspecialchars untuk mensanitasi input dari client. Meskipun secara fisik tidak ada input yang bisa disusupi oleh user, namun harus tetap berpegang pada prinsip dasar pengembangan website, yaitu jangan pernah percaya apa yang dikirimkan oleh client.

    Jika kode PHP di atas langsung dieksekusi tanpa melalui halaman lain, maka akan muncul pesan peringatan:

    Notice: Undefined index: HTTP_REFERER in /var/www/index.php on line 2

    Itu adalah pesan peringatan karena ada yang salah pada kode PHP. Untuk memperbaiki kesalahan itu bisa dipelajari di sini.

    <?php
      $url = isset($_SERVER['HTTP_REFERER']) ? htmlspecialchars($_SERVER['HTTP_REFERER']) : '';
    ?>
      <a href="<?=$url?>">Go Back PHP</a>
    

    Dalam artikel singkat ini selain dipelajari cara membuat tombol “back” namun juga pentingnya menulis kode yang baik dan berkualitas. Kode yang baik dan berkualitas akan membuat website yang dibuat menjadi lebih aman. Mulailah menulis kode yang berkualitas dari kasus yang paling sederhana.