Membuat REST API CRUD dengan Laravel serta JWT

Membuat REST API CRUD dengan Laravel serta JWT
Konten Halaman

Di kesempatan kali kita akan membahas bagaimana cara membuat REST API Laravel versi 8 dengan sistem API CRUD(Create, Read, Update, Delete) disertai JWT(Javascript Web Token) untuk kebutuhan membuat autentikasi dengan bantuan Laravel Passport sebagai alternatif laravel sanctum sehingga sistem bisa digunakan sebagai backend untuk keperluan REST untuk dikonsumsi di bahasa pemrograman lain seperti di Android Studio, Vue Js Frontend di laravel dan kebutuhan web service lainnya.

Fitur yang akan bangun mencakup sistem Login atau Logout, Register, Update dan Delete dengan studi kasus simple user, diamana API sebagai backend ini bisa melakukan perubahan bagian profile, seperi update name, email, dan password disertai enkripsi bycrypt.

Install Laravel versi terbaru

di tulisan ini saya melakukan instalasi laravel versi 8.x

composer create-project laravel/laravel:^8.0 rest-api-laravel

Penjelasan :

  • melakukan install laravel versi 8 di PC kita dengan bantuan composer

kemudian install laravel passport dari composer

Install Laravel Passport API

composer require laravel/passport

Penjelasan :

  • melakukan intall library passport yang di kembangkan oleh laravel dengan library tersebut kita bisa menggunakan JWT (Javascript web token), maka untuk mengakses sebuah api yang diharuskan autentikasi harus disertai sebuah http header Authorization : Bearer {TOKEN_JWT}

Menyiapkan Database di Laravel

Jangan lupa kita setup terlebih dahulu untuk bisa terhubung dengan database, disini kami menggunakan database mysql untuk menyimpan data dari laravel api dan menggunakan database dengan nama rest-api-laravel, maka isi file .env yang kita punya akan seperti berikut:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=rest-api-laravel
DB_USERNAME=root
DB_PASSWORD=

Penjelasan :

  • DB_CONNECTION : database yang kita gunakan disini kami menggunakan database mysql untuk menyimpan data.
  • DB_HOST : alamat host mysql
  • DB_PORT : port yang digunakan oleh mysql
  • DB_DATABASE : nama database mysql yang akan digunakan
  • DB_USERNAME : username untuk mengakses database mysql
  • DB_PASSWORD : password yang digunakan oleh mysql

setingan .env disesuaikan dengan konfigurasi mysql teman - teman

bagi teman teman yang kesulitan untuk membuat database di mysql bisa kunjungi tutorial saya di cara membuat databse mysql

lalu lakukan migrate database dengan perintah ini :

php artisan migrate

dan kita install dan apply laravel passport sudah berhasil terkoneksi dengan database mysql di laravel, karena laravel passport membutuhkan koneksi ke database untuk keperluan membuat beberapa tabel yang berhubungan dengan JWT

php artisan passport:install

Selanjutnya tambahkan di file Model User.php sebuah kode memanggil HasApiTokens - use Laravel\Passport\HasApiTokens; dan tambahkan use HasApiTokens di dalam class User bisa di ikuti seperti contoh kode dibawah ini :

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

use Laravel\Passport\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;
}

Penjelasan :

  • class User di inject oleh dependensi HasApiTokens yang berasal dari laravel Passport, maka akan ada fitur dari laravel password ketika kita memanggil model User

kemudian update file config/auth.php ubah dari driver token ke driver passport seperti berikut :

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'passport',
            'provider' => 'users',
            'hash' => false,
        ],
    ],

Penjelasan :

  • pada bagian key api kita ubah value driver ke value passport, tujuannya untuk mengganti setiap melakukan login di endpoint api

Modifikasi Middleware Auth API Laravel

setelah itu kita setup middleware untuk keperluan pengecekan autentikasi, mengedit middleware pengecekan autentikasi, isi dari Authenticate.php dirubah menjadi seperti berikut :

<?php

namespace App\Http\Middleware;

use Illuminate\Auth\Middleware\Authenticate as Middleware;

class Authenticate extends Middleware
{

    protected function redirectTo($request)
    {
        // if (! $request->expectsJson()) {
        //     return route('login');
        // }

        if(empty($request->header('Authorization'))){
            header('HTTP/1.0 401');
            echo 'Unauthorization';
            die();
        }
    }
}

Penjelasan :

  • if(empty($request->header('Authorization'))){ : melakukan pengecekan apakah ada header bernama key Authorization ketika melakukan request api jika tidak ada maka dinyatakan Unauthorization.

Membuat Repository User

di project ini kami menggunakan pola atau pattern Repository yang dimana nanti akan melakukan pengaksesan ke database seperti melakukan query akan dilakukan di folder Repository dan dilanjutkan ke Controller

Repository User melakukan Create

kita beri nama repository dengan nama UserRepository.php yang disimpan dalam folder \rest-api-laravel\app\Repositories\UserRepository.php yang isinya kode berikut:

<?php

namespace App\Repositories;

use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;

class UserRepository
{

    public function createAndLogin($input)
    {
        try {
            $user = User::create([
                'name' => $input['name'],
                'email' => $input['email'],
                'password' => bcrypt($input['password']),
            ]);

            if ($user->save()) {
                $result['status']   = true;
                $result['code']     = 201;
                $result['message']  = "Berhasil Membuat User baru";

                $authUser = [
                    'email' => $input['email'],
                    'password' => $input['password'],
                ];

                if (auth()->attempt($authUser)) {
                    $user       = Auth::user();
                    $objToken   = auth()->user()->createToken('LaravelAuthApp');
                    $strToken   = $objToken->accessToken;
                    $expiration = $objToken->token->expires_at->diffInSeconds(Carbon::now());

                    $result = array_merge($result, [
                      'token'       => $strToken,
                      'expires_in'  => $expiration
                    ]);
                }

                return $result;
            } else {
                $result['status']   = false;
                $result['code']     = 500;
                $result['message']  = "Gagal Membuat User baru";
                $result['user']     = (object)[];
                return $result;
            }
        } catch (\Exception $e) {
            $result['status']       = false;
            $result['code']         = 500;
            $result['message']      = "Gagal Update User";
            $result['user']         = (object)[];
            $result['error'] = [
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line_of_code' => $e->getLine(),
                'code' => $e->getCode(),
            ];
            return $result;
        }
    }

    public function update($input = [])
    {
        $user = Auth::user();

        if (isset($input['password'])) {
            $input['password'] = bcrypt($input['password']);
        }

        try {
            if ($user->update($input)) {
                $result['code']       = 200;
                $result['status']     = true;
                $result['message']    = "Berhasil Update user";
                $result['user']       = $user;
            }

            return $result;
        } catch (\Exception $e) {
            $result['status']       = false;
            $result['code']         = 500;
            $result['message']      = "Gagal Update User";
            $result['user']         = (object)[];
            $result['error'] = [
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line_of_code' => $e->getLine(),
                'code' => $e->getCode(),
            ];
            return $result;
        }
    }

    public function delete($id)
    {
        $user = User::id($id);

        try {
            if ($user->delete($id)) {
                $result['code']       = 200;
                $result['status']     = true;
                $result['message']    = "Berhasil Delete user";
                $result['user']       = $user;
            }

            return $result;
        } catch (\Exception $e) {
            $result['status']       = false;
            $result['code']         = 500;
            $result['message']      = "Gagal Delete User";
            $result['user']         = (object)[];
            $result['error'] = [
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line_of_code' => $e->getLine(),
                'code' => $e->getCode(),
            ];
            return $result;
        }
    }
}

Penjelasan :

  • di repo ini kami melakukan pengecekan User::firstOrNew([
  • 'password' => bcrypt($input['password']) melakukan enkripsi password
  • auth()->attempt($authUser) untuk langsung login ketika registrasi

Membuat controller User

membuat controller dengan nama file UserController.php yang mengakses ke file repository UserRepository.php

<?php

namespace App\Http\Controllers;

use App\Repositories\UserRepository;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use PhpParser\Node\Stmt\TryCatch;

class UserController extends Controller
{
  public function register(Request $request)
  {
    $inputRequest = $request->input();
    $validator = Validator::make($inputRequest, [
        'email'     => 'unique:users,email|required|string',
        'name'      => 'required|string',
        'password'  => 'required|string',
    ]);

    if ($validator->fails()) {
      $error                = $validator->messages()->first();
      $response['status']   = false;
      $response['message']  = $error;
      return response()->json($response, 400);
    }

    $userRepo   = new UserRepository();
    $response   = $userRepo->createAndLogin($inputRequest);
    $statusCode = $response['code'];
    unset($response['code']);

    return response()->json($response, $statusCode);
  }

  public function login(Request $request)
  {
    $input_request = $request->input();
    $validator = Validator::make($input_request, [
        'email'     => 'required|exists:users,email',
        'password'  => 'required',
    ]);

    if ($validator->fails()) {
      $error = $validator->messages()->first();
      $response['status'] = false;
      $response['message'] = $error;
      return response()->json($response, 400);
    }

    $data = [
        'email'     => $input_request['email'],
        'password'  => $input_request['password']
    ];

    if (auth()->attempt($data)) {
      $user       = Auth::user();
      $objToken   = auth()->user()->createToken('LaravelAuthApp');
      $strToken   = $objToken->accessToken;
      $expiration = $objToken->token->expires_at->diffInSeconds(Carbon::now());

      return response()->json([
        'token'       => $strToken,
        'expires_in'  => $expiration,
        'data'        => $user
      ], 200);

    } else {

      return response()->json([
        'error' => 'Email atau Password alah',
        'status' => false
      ], 401);

    }
  }

  public function profile(Request $request)
  {
    $user       = Auth::user();
    return response()->json($user, 200);
  }

  public function put(Request $request)
  {
    $user     = Auth::user();
    $input    = $request->all();

    $validator =  Validator::make($input,[
      'name' => 'string|required',
      'email' => 'unique:users,email,'.$user->id.',id|string|required',
      'password' => 'sometimes|required|string'
    ]);

    if ($validator->fails()) {
      $error = $validator->messages()->first();
      $response['status']   = false;
      $response['message']  = $error;
      return response()->json($response, 400);
    }

    $userRepo   = new UserRepository();
    $response   = $userRepo->update($input);

    $statusCode = $response['code'];
    unset($response['code']);

    if($response['status'] === true){
      return response()->json($response, $statusCode);
    }

    return response()->json($response, $statusCode);
  }

  public function patch(Request $request)
  {
    $user     = Auth::user();
    $input    = $request->all();

    $validator =  Validator::make($input,[
      'name' => 'sometimes|string|required',
      'email' => 'sometimes|unique:users,email,'.$user->id.',id|string|required',
      'password' => 'sometimes|required|string'
    ]);

    if ($validator->fails()) {
      $error = $validator->messages()->first();
      $response['status']   = false;
      $response['message']  = $error;
      return response()->json($response, 400);
    }

    $userRepo   = new UserRepository();
    $response   = $userRepo->update($input);

    $statusCode = $response['code'];
    unset($response['code']);

    if($response['status'] === true){
      return response()->json($response, $statusCode);
    }

    return response()->json($response, $statusCode);
  }

  public function delete(Request $request)
  {
    $user     = Auth::user();
    $userRepo   = new UserRepository();
    $response   = $userRepo->delete($user->id);

    $statusCode = $response['code'];
    unset($response['code']);

    if($response['status'] === true){
      return response()->json($response, $statusCode);
    }

    return response()->json($response, $statusCode);
  }

  public function logout(Request $request)
  {
    $request->user()->token()->revoke();
    return response()->json([
        'message' => 'Successfully logged out'
    ], 200);
  }
}

Membuat Route Endpoint URL

setelah selesai membuat controller lanjut kita endpoint di laravel, caranya adalah dengan menambahkan beberapa kode di dalamnya seperti memanggil controller di line awal use App\Http\Controllers\UserController; disertai endpoint yg kita inginkan, berikut kode route.php yang saya gunakan:

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

use  App\Http\Controllers\UserController;

Route::group(['middleware' => ['auth:api']], function (){
    Route::get('/user', [UserController::class, 'profile']);
    Route::patch('/user', [UserController::class, 'patch']);
    Route::post('/user/logout', [UserController::class, 'logout']);
    Route::post('/user/delete', [UserController::class, 'delete']);
});

Route::post('/register', [UserController::class, 'register']);
Route::post('/user/login', [UserController::class, 'login']);