Data Validation

NexaUI framework menyediakan sistem validasi data yang kuat dan fleksibel untuk memastikan data yang masuk ke aplikasi Anda memenuhi kriteria yang diharapkan.

Pengenalan Validasi Data

Validasi data adalah proses memeriksa apakah data yang diterima dari user atau sumber eksternal lainnya memenuhi aturan dan format yang diharapkan sebelum diproses lebih lanjut atau disimpan ke database.

Mengapa Validasi Penting?

  • Memastikan integritas data dalam aplikasi
  • Mencegah error dan crash yang disebabkan oleh data yang tidak valid
  • Meningkatkan keamanan aplikasi dengan mencegah input berbahaya
  • Memberikan feedback yang jelas kepada pengguna tentang kesalahan input
  • Mengurangi beban server dengan menolak data yang tidak valid sejak awal

Validasi Form di Controller

NexaController menyediakan metode validateForm() untuk validasi data form:

Validasi Dasar


// Di dalam controller
public function store(): void
{
    // Mendefinisikan aturan validasi
    $rules = [
        'username' => 'required|min:3|max:50|alpha_dash',
        'email' => 'required|email|unique:users',
        'password' => 'required|min:8|confirmed',
        'age' => 'required|numeric|min:18'
    ];
    
    // Melakukan validasi
    if (!$this->validateForm($rules)) {
        // Validasi gagal, redirect kembali dengan error
        $this->redirect('/register');
        return;
    }
    
    // Validasi berhasil, lanjutkan dengan menyimpan data
    $userData = [
        'username' => $this->getPost('username'),
        'email' => $this->getPost('email'),
        'password' => password_hash($this->getPost('password'), PASSWORD_DEFAULT),
        'age' => $this->getPost('age')
    ];
    
    $this->Storage('users')->insert($userData);
    $this->setFlash('success', 'User berhasil didaftarkan!');
    $this->redirect('/login');
}
        

Mendapatkan Data Validasi


// Validasi dan dapatkan data yang sudah divalidasi
$validatedData = $this->validateForm($rules, false);

if ($validatedData) {
    // Validasi berhasil, $validatedData berisi data yang sudah divalidasi
    $this->Storage('users')->insert($validatedData);
    $this->setFlash('success', 'User berhasil didaftarkan!');
    $this->redirect('/login');
} else {
    // Validasi gagal, tampilkan form kembali dengan error
    $this->render('auth/register');
}
        

Aturan Validasi

NexaUI mendukung berbagai aturan validasi yang dapat dikombinasikan dengan separator |:

Aturan Dasar

  • required - Field harus ada dan tidak boleh kosong
  • email - Field harus berupa alamat email yang valid
  • numeric - Field harus berupa angka
  • integer - Field harus berupa bilangan bulat
  • string - Field harus berupa string
  • array - Field harus berupa array
  • boolean - Field harus berupa boolean
  • date - Field harus berupa tanggal yang valid

Aturan Panjang dan Ukuran

  • min:value - Minimal panjang string, nilai numerik, atau ukuran array
  • max:value - Maksimal panjang string, nilai numerik, atau ukuran array
  • size:value - Panjang string, nilai numerik, atau ukuran array harus sama dengan value
  • between:min,max - Nilai harus berada di antara min dan max

Aturan Format

  • alpha - Field hanya boleh berisi huruf
  • alpha_num - Field hanya boleh berisi huruf dan angka
  • alpha_dash - Field hanya boleh berisi huruf, angka, dash (-) dan underscore (_)
  • url - Field harus berupa URL yang valid
  • ip - Field harus berupa alamat IP yang valid
  • json - Field harus berupa JSON string yang valid

Aturan Perbandingan

  • same:field - Field harus sama dengan field lain
  • different:field - Field harus berbeda dengan field lain
  • confirmed - Field harus memiliki field konfirmasi (field_confirmation)
  • in:foo,bar,... - Field harus ada dalam daftar nilai yang diberikan
  • not_in:foo,bar,... - Field tidak boleh ada dalam daftar nilai yang diberikan

Aturan Database

  • unique:table,column,except,id - Field harus unik di tabel database
  • exists:table,column - Field harus ada di tabel database

Aturan File

  • file - Field harus berupa file yang diupload
  • image - Field harus berupa file gambar (jpg, jpeg, png, bmp, gif, svg, webp)
  • mimes:jpg,png,... - File harus memiliki MIME type yang ditentukan
  • max_size:value - Ukuran file maksimal dalam kilobytes

Validasi Kustom

Anda dapat membuat aturan validasi kustom dengan menggunakan callback function:


// Mendefinisikan aturan validasi dengan callback
$rules = [
    'username' => 'required|min:3',
    'password' => 'required|min:8',
    'promocode' => function($value) {
        // Validasi kode promo kustom
        $validCodes = ['NEXA2023', 'SUMMER50', 'WELCOME10'];
        
        if (empty($value)) {
            return true; // Kode promo opsional
        }
        
        if (!in_array($value, $validCodes)) {
            return 'Kode promo tidak valid';
        }
        
        return true; // Validasi berhasil
    }
];

// Melakukan validasi
if (!$this->validateForm($rules)) {
    $this->render('register');
    return;
}
        

Menangani Error Validasi

Mengakses Error


// Cek apakah ada error pada field tertentu
if ($this->hasError('username')) {
    // Ada error pada field username
    $usernameError = $this->getFieldError('username');
    // ...
}

// Mendapatkan semua error
$errors = $this->getAllErrors();

// Mendapatkan nilai input sebelumnya
$oldUsername = $this->old('username');
        

Menampilkan Error di Template


{$error_username}
{/if}
{$error_email}
{/if}

Render dengan Validasi


// Validasi dan render form dengan error dan old values
public function register(): void
{
    if ($this->isPost()) {
        $rules = [
            'username' => 'required|min:3|max:50|alpha_dash',
            'email' => 'required|email|unique:users',
            'password' => 'required|min:8|confirmed'
        ];
        
        if ($this->validateForm($rules)) {
            // Validasi berhasil, proses data
            // ...
            return;
        }
        
        // Validasi gagal, form akan di-render dengan error
    }
    
    // Render form (dengan error jika validasi gagal)
    $this->renderWithValidation('auth/register');
}
        

Validasi AJAX

NexaController menyediakan metode untuk validasi AJAX:


// Endpoint API untuk validasi
public function validateRegistration(): void
{
    $rules = [
        'username' => 'required|min:3|max:50|alpha_dash|unique:users',
        'email' => 'required|email|unique:users',
        'password' => 'required|min:8'
    ];
    
    // Validasi dan dapatkan response
    $response = $this->validateWithResponse($rules);
    
    // Kirim response JSON
    $this->jsValidationResponse(
        $response['is_valid'],
        $response['errors'],
        ['redirect' => '/dashboard'],
        [],
        'Registrasi berhasil!',
        'Mohon perbaiki error berikut:'
    );
}
        

Validasi Field Tunggal


// Validasi field tunggal (untuk validasi real-time)
public function validateField(): void
{
    $field = $this->getPost('field');
    $value = $this->getPost('value');
    
    $result = [];
    
    switch ($field) {
        case 'username':
            $result = $this->validateSingleField($field, 'required|min:3|max:50|alpha_dash|unique:users');
            break;
        case 'email':
            $result = $this->validateSingleField($field, 'required|email|unique:users');
            break;
        // ...
    }
    
    $this->json($result);
}
        

Validasi di Model

Anda juga dapat melakukan validasi di level model:


// Di dalam model User
class User extends NexaModel
{
    protected $table = 'users';
    
    public function validate(array $data): array
    {
        $errors = [];
        
        // Validasi username
        if (empty($data['username'])) {
            $errors['username'] = 'Username tidak boleh kosong';
        } elseif (strlen($data['username']) < 3) {
            $errors['username'] = 'Username minimal 3 karakter';
        } elseif (!preg_match('/^[a-zA-Z0-9_-]+$/', $data['username'])) {
            $errors['username'] = 'Username hanya boleh berisi huruf, angka, dash dan underscore';
        } elseif ($this->isUsernameExists($data['username'])) {
            $errors['username'] = 'Username sudah digunakan';
        }
        
        // Validasi email
        if (empty($data['email'])) {
            $errors['email'] = 'Email tidak boleh kosong';
        } elseif (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
            $errors['email'] = 'Format email tidak valid';
        } elseif ($this->isEmailExists($data['email'])) {
            $errors['email'] = 'Email sudah digunakan';
        }
        
        // Validasi password
        if (empty($data['password'])) {
            $errors['password'] = 'Password tidak boleh kosong';
        } elseif (strlen($data['password']) < 8) {
            $errors['password'] = 'Password minimal 8 karakter';
        }
        
        return $errors;
    }
    
    private function isUsernameExists(string $username): bool
    {
        return $this->table($this->table)
                    ->where('username', $username)
                    ->exists();
    }
    
    private function isEmailExists(string $email): bool
    {
        return $this->table($this->table)
                    ->where('email', $email)
                    ->exists();
    }
}
        

Menggunakan Validasi Model di Controller


// Di dalam controller
public function register(): void
{
    if ($this->isPost()) {
        $userData = [
            'username' => $this->getPost('username'),
            'email' => $this->getPost('email'),
            'password' => $this->getPost('password')
        ];
        
        // Validasi menggunakan model
        $userModel = new User();
        $errors = $userModel->validate($userData);
        
        if (empty($errors)) {
            // Validasi berhasil, simpan data
            $userData['password'] = password_hash($userData['password'], PASSWORD_DEFAULT);
            $userModel->insert($userData);
            
            $this->setFlash('success', 'Registrasi berhasil!');
            $this->redirect('/login');
            return;
        }
        
        // Validasi gagal, set error dan old values
        foreach ($errors as $field => $message) {
            $this->setFieldError($field, $message);
        }
        
        $this->setOldValues($userData);
    }
    
    $this->render('auth/register');
}
        

Best Practices

  • Selalu validasi data input sebelum menyimpan ke database
  • Gunakan validasi di sisi client dan server untuk pengalaman pengguna yang lebih baik
  • Berikan pesan error yang jelas dan spesifik
  • Gunakan validasi bertingkat: form validation untuk input user, model validation untuk aturan bisnis
  • Sanitasi input setelah validasi untuk mencegah XSS dan SQL injection
  • Gunakan method renderWithValidation() untuk otomatis menampilkan error dan nilai lama
  • Untuk form yang kompleks, pertimbangkan untuk membuat Form Request class terpisah