Membuat Fitur Verifikasi Email pada Formulir Registrasi


Tulisan ini masih berhubungan dengan tulisan sebelumnya, ialah Membuat Sendiri Fitur dan Formulir Registrasi.

Di tutorial sebelumnya, kita sudah membuat formulir (form), validasi, dan simpan data pengguna baru disertai dengan auto-login untuk user tersebut.

Di tulisan ini, kita akan menambahkan fitur baru berupa verifikasi email, di mana ketika pengguna mendaftar, pengguna tersebut akan mendapatkan email yang berisi tautan (hyperlink) untuk verifikasi dan aktivasi akun. Sebelum email diverifikasi, maka (seharusnya) pengguna tersebut belum bisa masuk (login) ke dalam aplikasi.

Untuk menambahkan fitur verifikasi email, ada beberapa perubahan yang akan dilakukan berdasarkan skrip tutorial sebelumnya.

  • Penambahakan field status di tabel user. Field ini akan ditambahkan melalui migration dengan tipe data enum dengan nilai “pending” dan “activated”. Nilai asalnya adalah “pending”, dan akan diubah menjadi “activated” ketika pengguna memverifikasi alamat emailnya.
  • Penambahakan fitur kirim email di controller SignupController.

Untuk proses pengiriman email, kita dapat memanfaatkan fitur Mailable yang tersedia di Laravel 5.3 ke atas.

Alur proses registrasinya adalah sebagai berikut:

  1. Calon pengguna mendaftar melalui formulir registrasi (/signup).
  2. Validasi berhasil, data pengguna disimpan ke dalam pangkalan data (database) dan mengirimkan email berisi tautan verifikasi. Contoh tautannya berbentuk domain.com/verify?token=xxx. Di mana, nilai xxx merupakan pos-el (email) yang dienkripsi. Data ini nantinya didekripsi saat proses verifikasi.
  3. Apabila nilai xxx yang sudah didekripsi ditemukan dalam pangkalan data, maka akun pengguna bersangkutan diubah statusnya menjadi “activated”.

Menambahkan Field di tabel Pengguna (user)

Migration untuk tabel pengguna (user) sudah disediakan Laravel. Kita bisa memodifikasinya pada berkas 2014_10_12_000000_create_users_table.php dalam direktori database/migrations.

Tambahkan field status di dalamnya dengan menambahkan skrip di bawah:

/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->string('email')->unique();
        $table->string('password');
        $table->rememberToken();
        $table->enum('status', ['pending', 'activated'])->default('pending');
        $table->timestamps();
    });
}

Menambahkan Field pada Model

Jika kita menambahkan field baru pada tabel, tentunya, kita perlu menambahkan atribut tersebut pada model bersangkutan sebagai representasi field di tabel.

Pada berkas app\User.php, kita memodifikasi properti $fillable menjadi skrip di bawah.

/**
 * The attributes that are mass assignable.
 *
 * @var array
 */
protected $fillable = [
    'name',
    'email',
    'password',
    'status',
];

Membuat Mailable

Buat mailable dengan baru nama VerifyEmail menggunakan Artisan console.

$ php artisan make:mail VerifyEmail

Mail created successfully.

Mailable tersimpan dalam direktori app/Mail. Direktori app/Mail sendri otomatis dibuat jika belum tersedia.

Buka berkas VerifyMail.php dalam direktori app/Mail, dan tambahkan skrip lengkap seperti di bawah.

<?php

namespace App\Mail;

use App\User;
use Crypt;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class VerifyEmail extends Mailable
{
    use Queueable, SerializesModels;

    private $user;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct(User $user)
    {
        $this->user = $user;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        // generate link
        $encryptedEmail = Crypt::encrypt($this->user->email);

        // ex: domain.com/verify?token=xxxx
        $link = route('signup.verify', ['token' => $encryptedEmail]);

        return $this->subject('Verify Your Email Address')
            ->with('link', $link)
            ->view('email.signup');
    }
}

Pada skrip di atas, kita menggunakan route dengan nama signup.verify. Route ini akan kita buat pada bahasan di bawah.

Kita juga menggunakan facade Crypt untuk mengenkripsi data email pengguna.

Membuat View Email

Di skrip mailable di atas, kita mendefinisikan view email.signup. Itu artinya, kita harus membuat sebuah berkas template Blade dengan nama signup.blade.php di dalam direktori resources/views/email.

Contoh template email sederhananya adalah sebagai berikut.

<p>Click link below to verify your email address:</p>

<p>{{ $link }}</p>

<p>Thank you.</p>

Memodifikasi Method store() pada SignupController

Dalam method store() sudah ada alur untuk validasi, simpan data pengguna, dan auto login. Dari modifikasi kali ini, kita akan menghilangkan fitur auto login dan menggantinya dengan pengiriman email verifikasi.

Skrip lengkapnya dapat diamati pada media di bawah. Perhatikan, kita mengimpor mailable yang sudah dibuat di atas ke dalam SignupController.

public function store(Request $request)
{
    // validate request data
    $this->validate($request, [
        'name' => 'required|string|max:50',
        'email' => 'required|email|max:100|unique:users,email',
        'password' => 'required|min:6',
        'confirm_password' => 'required|same:password',
    ]);

    DB::transaction(function () use ($request) {
        // save into table
        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => bcrypt($request->password),
        ]);

        // send email verification
        Mail::to($user->email)->send(new VerifyEmail($user));
    });

    // redirect to home
    return redirect()->back();
}

Selain mailable, kita juga menggunakan facade Crypt untuk mendekripsi token yang terdapat pada tautan.

Membuat Method Verifikasi Email

Pada controller SignupController, tambahkan method baru dengan nama verify(). Method ini berfungsi untuk memproses token yang ada pada tautan verifikasi, mendekripsi token, dan mencocokkannya ke dalam pangkalan data pengguna.

public function verify()
{
    if (empty(request('token'))) {
        // if token is not provided
        return redirect()->route('signup.form');
    }

    // decrypt token as email
    $decryptedEmail = Crypt::decrypt(request('token'));

    // find user by email
    $user = User::whereEmail($decryptedEmail)->first();

    if ($user->status == 'activated') {
        // user is already active, do something
    }

    // otherwise change user status to "activated"
    $user->status = 'activated';
    $user->save();

    // autologin
    Auth::loginUsingId($user->id);

    return redirect('/home');
}

Skrip lengkap SignupController dapat dilihat pada Gist Github.

Mendaftarkan Method Verifikasi pada Route

Jangan lupa, untuk menambahkan method tersebut pada route. Selain itu, kita juga memberi nama pada path yang didaftarkan.

Route::get('verify', 'SignupController@verify')->name('signup.verify');

Mengkonfigurasi SMTP Email

Ada banyak layanan yang menyediakan SMTP Relay, seperti Mailgun, Google, ElasticEmail, dan lain sebagainya.

Khusus untuk tahap pengembangan, kita bisa menggunakan layanan Mailtrap.io. Nantinya, semua email yang dikirim akan masuk ke dalam satu kotak masuk.

Silakan mendaftar sebagai pengguna di Mailtrap, kemudian ubah pengaturan pada berkas .env sesuai dengan konfigurasi yang diberikan oleh Mailtrap. Pastikan komputer kalian terhubung dengan internet untuk menggunkan layanan Mailtrap.

Ujicoba

Tahap ujicoba ada beberapa langkah, dan tidak jauh berbeda dengan langkah yang saya jabarkan pada tulisan sebelumnya.

Untuk memastikan fitur berjalan dengan benar, cobalah untuk mengakses halaman /signup dari peramban, isi data pengguna di sana, dan periksa apakah email verifikasi sudah masuk?

Pesan masuk pada Mailtrap

Jika email sudah masuk, cobalah menyalin tautan verifikasi tersebut pada peramban untuk mengaktifkan akun yang terdaftar sebelumnya. Berhasil? Semoga saja aplikasi berjalan dengan sempurna. 😀

Konklusi

Jika kita menggunakan fitur login yang disediakan oleh Laravel, maka status apapun tidak berpengaruh (baik “pending” maupun “activate”). Padahal, semestinya status yang masih “pending” belum bisa login dan butuh verifikasi email terlebih dahulu.

Nah, untuk menangani kasus di atas, kita bisa membuat fitur login sendiri yang juga memeriksa status pengguna. Bahasan membuat login di Laravel akan saya jabarkan pada tulisan berikutnya. 😉

***

Tulisan juga dapat dibaca pada Publikasi Medium Laravel Indonesia.

 

Tak Berkategori

Yugo Purwanto

Pemrogram PHP dan JavaScript yang sedang sibuk mengembangkan aplikasi Glosarium Bahasa Indonesia.

5 comments

  1. sudah ngikutin kug, saya make laravel 5.5 dan sudah solved sekarang dengan nambahin di route:

    Route::resource(‘signup’, ‘SignupController’);

    entah itu karena apa tapi bisa.

  2. oiya mas, ada yang kurang dijelaskan penambahan element use nya di SignupController, seperti berikut:

    use App\Mail\VerifyEmail;
    use Illuminate\Support\Facades\Crypt;
    use DB;

    dan di VerifyEmail.php:

    use Illuminate\Support\Facades\Crypt;

    karena make use Crypt aja gabisa

    selanjutnya sukses semua, terimakasih mas buat tutorialnya

Tinggalkan Balasan