Membuat REST API CRUD dengan Laravel serta JWT
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 mysqlDB_PORT
: port yang digunakan oleh mysqlDB_DATABASE
: nama database mysql yang akan digunakanDB_USERNAME
: username untuk mengakses database mysqlDB_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 dependensiHasApiTokens
yang berasal dari laravel Passport, maka akan ada fitur dari laravel password ketika kita memanggil modelUser
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 valuedriver
ke valuepassport
, 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 keyAuthorization
ketika melakukan request api jika tidak ada maka dinyatakanUnauthorization
.
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 passwordauth()->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']);