Membuat fitur email aktivasi pada saat registrasi di Laravel 5.4

Membuat fitur email aktivasi pada saat registrasi di Laravel 5.4

Ada diskusi di Laravel Group tentang Sentinel yang memiliki fitur email aktivasi pada saat registrasi. Untuk membuat fitur tersebut, apakah bisa tanpa bantuan package dari pihak ketiga? Jawabannya tentu saja bisa.

Sebelum dimulai, saya asumsikan Laravel anda sudah terkonfigurasi dengan benar. Sehingga sudah bisa mengirimkan email dan save data ke database.

Migration

Hal pertama yang perlu anda lakukan adalah menambahkan dua field ke users table. Kira-kira begini migration-nya.

$table->string('activation_token')->nullable()->unique();
$table->datetime('activated_at')->nullable();

Mail

Setelah itu, jalankan perintah artisan berikut

php artisan make:mail UserActivation -m emails/activation

Perintah di atas akan men-generate dua file, yaitu app/Mail/UserActivation.php dan resources/views/emails/activation.blade.php

Edit file app/Mail/UserActivation.php

Tambahkan public property $user dan parameter $user ke __construct. Juga sedikit modifikasi pada method build. Kira-kira menjadi seperti ini

public $user;

public function __construct(User $user)
{
    $this->user = $user;
}

public function build()
{
    return $this->markdown('emails.verification', $this->user->toArray());
}

Berikutnya kita edit file resources/views/emails/activation.blade.php

@component('mail::message')
# Activate your account

Klik link berikut untuk mengaktifkan akun anda.

@component('mail::button', ['url' => url('activation/' . $user->activation_token) ])
Aktifkan!
@endcomponent

Thanks,

{{ config('app.name') }}
@endcomponent

Route

Edit routes/web.php, tambahkan route baru untuk handle activation token

Route::get('activation/{token}', function ($token)
{
    $user = App\User::where('activation_token', $token)->first();

    if ($user) {
        $user->activated_at = \Carbon\Carbon::now();
        $user->save();

        return 'Your account has been activated.';
    }

    return 'Invalid activation token.';
});

Registrasi

Agar tutorialnya simple dan seragam, saya asumsikan anda menggunakan php artisan make:auth untuk membuat registrasi.

Tambahkan method di bawah ini ke app/Http/Controllers/Auth/RegisterController.php

protected function registered(Request $request, $user)
{
    \Mail::to($user)->send(new \App\Mail\UserActivation($user));

    return 'Please check your mail box.';
}

Masih di file yang sama, pada method create, tambahkan activation_token

protected function create(array $data)
{
    return User::create([
        'name' => $data['name'],
        'email' => $data['email'],
        'password' => bcrypt($data['password']),

         // Tambahin ini nih...
         // Btw, jangan lupa nambahin 'activation_token' pada
         // property $fillable di file app/User.php
        'activation_token' => str_random(64),
    ]);
}

Selesai! Sekarang anda bisa coba lakukan registrasi. Lalu cek email, dan visit URL yang ada di email.

Kesimpulan

Membuat fitur mengirimkan email untuk aktivasi di Laravel sangat mudah. Sehingga penggunaan package tambahan tidak diperlukan.

Anda juga bisa mengubah fitur aktivasi lewat email menjadi aktivasi yang lain. Misalnya aktivasi menggunakan SMS dengan menggunakan fitur Notification di Laravel.

Contoh source code bisa dilihat di https://github.com/mul14/demo-account-activation-via-email-laravel54

Multiple .env di Laravel

Multiple .env di Laravel

Singkat cerita saya butuh konfigurasi yang berbeda-beda di tiap sub-domain, tapi dengan menggunakan core aplikasi yang sama. Maksudnya gini, kalau membuat sub-domain, maka ada folder khusus untuk sub-domain. Isi sub-domain ini adalah isi dari folder public. Misalnya begini struktur folder-nya

~/company1.example.com
  company2.example.com
  company3.example.com
  main_app

Nah, lokasi aplikasi utama ada di main_app. Sedangkan company1/2/3 maunya menggunakan core-nya si main_app tapi dengan konfigurasi environment dan database yang berbeda. Gimana caranya? :/

Update bootstrap/app.php

Tambahkan ini sebelum return $app;

if (is_readable(getcwd().'/.env')) {
    $app->useEnvironmentPath( getcwd() );
}

Yup, selesai 😀

Sekarang kalau menuju ke http://company1.example.com, maka akan menggunakan konfigurasi dari company1.example.com/.env

Weits, jangan lupa juga file .env diamankan. Kalau menggunakan Apache HTTPD

<Files ".env">
    Order Allow,Deny
    Deny from all
</Files>

Nginx

location ~ /\.env
{ 
    deny all; 
}

How to use “Laravel facade” outside of Laravel

How to use “Laravel facade” outside of Laravel

I love Laravel facade. With Laravel facade the code be more beautiful and readable than traditional approach. But, what if you don’t use Laravel? How to use the “facade”?

For example, I want to use Laravel “File” facade inside of my application.

First, I need to install illuminate/filesystem via composer.

composer require illuminate/filesystem

Then, just load the composer autoloader and create a new class like this

<?php

require 'vendor/autoload.php';

use Illuminate\Filesystem\Filesystem;

class File
{
    public static function __callStatic($name, $args)
    {
        $self = new Filesystem;

        return $self->{$name}(...$args);
    }
}

Finally, we can use File:: like in Laravel.

File::allFiles('./');

File::get('somefile.txt');

UPDATE 23 Aug 2016 – illuminate/config

For example I have folder structure like this

\ - assets/
  - config/
     \ - database.php
       - site.php
       - mail.php

Inside of database.php, site.php, mail.php just simple array. Example of database.php

<?php

return [
    'hostname' => 'localhost',
    'username' => 'root',
    'password' => '',
    'database' => 'test',
];

Here’s the main file to load all configurations.

<?php

require 'vendor/autoload.php';

use Illuminate\Config\Repository;

class Config
{
    protected static $instance;

    public static function __callStatic($method, $args)
    {
        if (! static::$instance) {
            static::$instance = new Repository(
                (new self)->loadConfig('config')
            );
        }

        return static::$instance->{$method}(...$args);
    }

    protected function loadConfig($configPath)
    {
        $items = [];

        foreach(scandir($configPath) as $file) {
            if (substr($file, -4) === '.php') {
                $filename = str_replace('.php', '', $file);
                $items[$filename] = require $configPath . '/' . $file;
            }
        }

        return $items;
    }
}

To get the configuration, just use Config::

Config::get('database.username');             // root
Config::set('database.username', 'newuser');  // Set new value
Config::get('database.username');             // newuser

Config::all();  // All configs

How to use Illuminate/Validation outside of Laravel

How to use Illuminate/Validation outside of Laravel

Ok, judulnya english, tapi isinya Indonesia. 😐

Kebetulan hari ini ada pertanyaan di Facebook Group Laravel Indonesia tentang bagaimana cara menggunakan Validator-nya Laravel tapi bukan di dalam project Laravel?

Ini dia enaknya Laravel, kita bisa menggunakan component-nya di luar Laravel itu sendiri. Ngg… sebenernya bukan cuma Laravel sih. Symfony, ZF, CakePHP, Aura, dll juga bisa digunakan component-nya di luar framework-nya sendiri. Mungkin pengecualian untuk Yii. Component di Yii terlalu terikat dengan framework-nya. Sehingga sangat sulit menggunakan component di Yii tanpa Yii. 😐 Itu salah satu alasan saya kurang suka Yii. Karena nggak mau berbagi dengan komunitas PHP secara keseluruhan.

Ok, kembali ke topik utama. Saya anggap kita bikin project from scratch. Pertama bikin folder project, setelah itu gunakan composer init untuk generate file composer.json

Ambil illuminate/validation dengan composer require illuminate/validation.

Buat file baru index.php dan load composer autoloader.

<?php
require __DIR__.'/vendor/autoload.php';

Kalau kita lihat di vendor/Illuminate/Validation/, ada file Factory.php. Factory adalah istilah yang umum digunakan untuk membuat suatu object.

Tambahkan code berikut.

<?php
require __DIR__.'/vendor/autoload.php';

$validator = new Illuminate\Validation\Factory();

Hmm, untuk membuat Validation\Factory kita membutuhkan Translator dari Symfony. Ini digunakan untuk menentukan error message dalam bahasa apa. Jadi kita tambahkan Symfony Translator

<?php
require __DIR__.'/vendor/autoload.php';

$trans = new Symfony\Component\Translation\Translator($locale = 'en');
$validator = new Illuminate\Validation\Factory($trans);

Nah, sekarang $validator sudah bisa digunakan 😀 Mari kita coba

<?php
require __DIR__.'/vendor/autoload.php';

$trans = new Symfony\Component\Translation\Translator($locale = 'en');
$validator = new Illuminate\Validation\Factory($trans);

$validation = $validator->make([
  'name' => ''
  'email' => 'hello'
],[
  'name' => 'required'
  'email' => 'required|email'
]);

var_dump($validation->fails()); // Seharusnya true

Ok, that’s it 😀 Selamat bereksperimen! Kalau ada pertanyaan, jangan ditanyakan. 😐

Postman sebagai XML-RPC Client

Postman sebagai XML-RPC Client

Hari ini kebetulan saya harus bermain-main dengan XML RPC di WordPress karena mau bikin fitur auto-post dari aplikasi yang dibikin dengan NodeJS. Untuk mengakses xmlrpc.php di WordPress, awalnya saya menggunakan curl. Ternyata… Lihat ini deh kak. 😥

xml-rpc

Seperti yang terlihat pada screenshot, menggunakan XML di command line itu gak enak dan bisa bikin pusing. Padahal itu masih XML yang sederhana. Gimana kalau udah banyak? :O

Walaupun di command line kita bisa menggunakan “new line”, tapi tetap aja pusing. -_-

Postman to the rescue

Setelah melihat sekilas pola dengan menggunakan curl, saya langsung buka Postman. Tinggal set header dengan Content-type: text/xml, lalu pada body ganti menjadi “raw”. Dan, tadaaa… enak enak :3

postman-as-xmlrpc-client
Click to zoom in

Multiple Authentication di Laravel 5.2

Multiple Authentication di Laravel 5.2

Pada kisah sebelumnya saya sebenarnya ingin mencari konfigurasi multiple authentication. Tapi malah nyasar ke token authentication.

Dengan multi-auth ini kita bisa membuat fitur login dengan table yang berbeda-beda dengan lebih mudah. Misalnya ada table dokter, pasien, dan staff.

Di Laravel 4, anda bisa menggunakan ollieread/multiauth untuk menggunakan multiple auth. Atau Kbwebs/MultiAuth untuk Laravel 5.0 dan 5.1.

Tetapi pada Laravel 5.2, Taylor Otwell menambahkan fitur ini ke core Laravel

So, gimana cara menggunakan multiple auth ini? Sangat mudah, tidak jauh berbeda dengan dua kisah sebelumnya. Kita bisa baca informasi pada config/auth.php

Screen Shot 2015-12-18 at 22.00.12

Jadi kita cukup menambahkan guards dan providers.

Persiapan

Contoh misalnya kita ingin ada tiga jenis user:

  • Doctor
  • Patient
  • Staff

Buat model yang mirip dengan app/User.php. Kita bisa copy dan edit nama class-nya. Jangan lupa buat juga  migrations untuk model tersebut. Isinya bisa copy dari /database/migrations/2014_10_12_000000_create_users_table.php, atau anda bisa buat sendiri sesuai dengan kebutuhan.

Setelah itu edit config/auth.php, tambahkan tiga guards dan tiga providers baru.

'guards' =>  [
    'doctor' =>  [
        'driver'   => 'session',
        'provider' => 'doctor',
    ],

    'patient' =>  [
        'driver'   => 'session',
        'provider' => 'patient',
    ],

    'staff' =>  [
        'driver'   => 'session',
        'provider' => 'staff',
    ],
],

// ... 

'providers' =>  [
    'doctor' =>  [
        'driver' => 'eloquent',
        'model'  => App\Doctor::class,
    ],

    'patient' =>  [
        'driver' => 'eloquent',
        'model'  => App\Patient::class,
    ],

    'staff' =>  [
        'driver' => 'eloquent',
        'model'  => App\Staff::class,
    ],
],

Login

Persiapan selesai. Saatnya simulasi untuk login. Eits, jangan lupa tambahkan user pada masing-masing model.

Berikut adalah file app/Http/routes.php

Route::get('/login', function() {

    $auth = auth()->guard('doctor'); // Atau \Auth::guard('doctor')

    $credentials = [
        'nip' =>  '04324321', // Nomor Induk Pegawai
        'password' =>  'sate',
    ];

    if ($auth->attempt($credentials)) {
        return 'Yay! Berhasil login (^o^)/';
    }

    return 'Gagal login.';

});

Well done 😀

UPDATE 19 Jan 2016 23:33:56

Pada Laravel 5.2 terbaru, tepatnya 5.2.10, kita bisa gunakan

auth('doctor')

lebih singkat daripada

auth()->guard('doctor')

Detailnya bisa dilihat di https://github.com/laravel/framework/commit/2edaa2791317e1ff0cf80a5d8539e983154082c1.

UPDATE 18 Maret 2016 08:26

Source code demo bisa dilihat di https://github.com/mul14/laravel-52-multiple-auth-demo