Laravel Core Root Prasyarat:
Dwonload zip PHP versi NTS, kemudian ekstrak dan rename folder nya menjadi php. Kemudian masukkan ke dalam path dan cek menggunakan cmd.
php -v
extension_dir = "ext"
extension=openssl
extension=zip
extension=fileinfo
extension=pgsql
extension=pdo_pgsql
extension=gmp
Install Composer
@echo off
php "%~dp0composer.phar" %*
composer create-project --prefer-dist laravel/laravel laracroot
Buat database di supabase kemudian masukkan ke .env
DB_CONNECTION=pgsql
DB_HOST=your-supabase-host.supabase.co
DB_PORT=5432
DB_DATABASE=your-database-name
DB_USERNAME=your-database-username
DB_PASSWORD=your-database-password
Category
. Dengan field: id, name, is_publish (boolean), created_at, dan updated_atphp artisan make:model Category -m
maka akan menghasilkan file Model: app/Models/Category.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use HasFactory;
protected $fillable = ['name', 'is_publish'];//opsional bisa di tambahkan baris ini
}
$fillable: Properti ini menentukan kolom mana yang bisa diisi secara massal. Anda bisa menambah atau mengurangi kolom yang diizinkan sesuai kebutuhan.
database/migrations/
dan tambahkan kolom yang diperlukan, contoh:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name'); // Kolom name
$table->boolean('is_publish')->default(true); // Kolom is_publish dengan nilai default true
$table->timestamps();//created_at dan updated_at
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('categories');
}
};
php artisan migrate
Dengan langkah-langkah ini, Anda telah berhasil membuat model Category dan migration yang sesuai. Model ini siap digunakan untuk berinteraksi dengan tabel categories di database.
Berikut adalah langkah-langkah untuk membuat factory dan seeder untuk model Category
serta memasukkan 100 data menggunakan Faker:
Category
Pertama, kita perlu membuat factory untuk model Category
. Anda dapat membuat factory menggunakan perintah berikut:
php artisan make:factory CategoryFactory --model=Category
Ini akan membuat file CategoryFactory
di direktori database/factories/
.
Buka file CategoryFactory.php
di database/factories/
dan edit seperti berikut:
<?php
namespace Database\Factories;
use App\Models\Category;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Category>
*/
class CategoryFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
protected $model = Category::class;//opsional tambahan baris ini lihat di model jika disana ada maka tambahkan ini
public function definition(): array
{
return [
'name' => $this->faker->word, // Menghasilkan nama kategori acak
'is_publish' => $this->faker->boolean, // Menghasilkan nilai true/false secara acak
'created_at' => now(),
'updated_at' => now(),
];
}
}
Category
Sekarang, kita akan membuat seeder untuk mengisi tabel categories
dengan data dari factory. Jalankan perintah berikut untuk membuat seeder:
php artisan make:seeder CategorySeeder
Ini akan membuat file CategorySeeder.php
di direktori database/seeders/
.
Buka file CategorySeeder.php
di database/seeders/
dan edit seperti berikut:
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Category;
class CategorySeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
// Menggunakan factory untuk membuat 100 data kategori
Category::factory()->count(100)->create();
}
}
Untuk menjalankan seeder dan mengisi tabel categories
dengan 100 data contoh, Anda bisa menjalankan perintah berikut:
php artisan db:seed --class=CategorySeeder
Opsional, jika Anda ingin menjalankan semua seeder sekaligus, Anda bisa mengedit file DatabaseSeeder.php
untuk memanggil CategorySeeder
:
public function run()
{
$this->call(CategorySeeder::class);
}
Kemudian jalankan:
php artisan db:seed
Menjalankan seeder ini akan mengisi tabel categories
dengan 100 data acak yang dihasilkan oleh Faker, sesuai dengan definisi dalam factory.
Pada bagian ini kita akan membuat controller dan menambahkannya ke route
php artisan make:controller CategoryController --resource
CategoryController
dengan metode CRUD (Create, Read, Update, Delete) dasar.bootstrap/app.php
agar mendeklarasikan api.php:
<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
api: __DIR__.'/../routes/api.php',//tambahan untuk api
commands: __DIR__.'/../routes/console.php',
health: '/up',
apiPrefix: '/api',//prefix untuk api
)
->withMiddleware(function (Middleware $middleware) {
//
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();
routes/api.php
dan tambahkan route untuk resource Category
:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\CategoryController;
Route::apiResource('categories', CategoryController::class);
php artisan route:list
CategoryController.php
dan implementasikan logika CRUD. Contoh implementasi untuk metode store
(POST), index
(GET), dan update
(PUT):use App\Models\Category; // Pastikan Anda mengimpor model Category di sini
GET: Mengambil Data
public function index()
{
return Category::all();
}
POST: Menambahkan Data
public function store(Request $request)
{
$post = Category::create($request->all());
return response()->json($post, 201);
}
PUT: Mengupdate Data
public function update(Request $request, $id)
{
$post = Category::findOrFail($id);
$post->update($request->all());
return response()->json($post, 200);
}
DELETE: Menghapus Data
public function destroy(string $id)
{
// Cari kategori berdasarkan ID
$category = Category::findOrFail($id);
// Hapus kategori
$category->delete();
// Kembalikan respon JSON yang menunjukkan berhasil
return response()->json(['message' => 'Category deleted successfully'], 200);
}
POST
http://127.0.0.1:8000/api/categories
{"name":"asep","is_publish":true}
php artisan serve
http://localhost:8000
.Berikut adalah contoh controller untuk model User
yang dapat Anda gunakan untuk mengelola pengguna dalam aplikasi Laravel. Controller ini akan memiliki metode CRUD (Create, Read, Update, Delete) dasar yang mirip dengan yang sudah kita buat untuk Category
.
Untuk membuat UserController
, Anda bisa menggunakan perintah Artisan berikut:
php artisan make:controller UserController --resource
Perintah ini akan membuat UserController
di dalam direktori app/Http/Controllers
dengan metode CRUD standar.
Berikut adalah contoh implementasi dari UserController
dengan metode CRUD dasar:
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* Display a listing of the users.
*
* @return \Illuminate\Http\JsonResponse
*/
public function index()
{
// Mendapatkan semua pengguna
$users = User::all();
return response()->json($users, 200);
}
/**
* Store a newly created user in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function store(Request $request)
{
// Validasi input
$validatedData = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8',
]);
// Buat pengguna baru
$user = User::create([
'name' => $validatedData['name'],
'email' => $validatedData['email'],
'password' => bcrypt($validatedData['password']),
]);
return response()->json($user, 201);
}
/**
* Display the specified user.
*
* @param int $id
* @return \Illuminate\Http\JsonResponse
*/
public function show($id)
{
// Cari pengguna berdasarkan ID
$user = User::findOrFail($id);
return response()->json($user, 200);
}
/**
* Update the specified user in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\JsonResponse
*/
public function update(Request $request, $id)
{
// Validasi input
$validatedData = $request->validate([
'name' => 'sometimes|required|string|max:255',
'email' => 'sometimes|required|string|email|max:255|unique:users,email,' . $id,
'password' => 'sometimes|required|string|min:8',
]);
// Cari pengguna berdasarkan ID
$user = User::findOrFail($id);
// Update data pengguna
$user->update($validatedData);
return response()->json($user, 200);
}
/**
* Remove the specified user from storage.
*
* @param int $id
* @return \Illuminate\Http\JsonResponse
*/
public function destroy($id)
{
// Cari pengguna berdasarkan ID
$user = User::findOrFail($id);
// Hapus pengguna
$user->delete();
return response()->json(['message' => 'User deleted successfully'], 204);
}
}
Untuk menghubungkan controller dengan rute, tambahkan rute berikut di routes/api.php
:
use App\Http\Controllers\UserController;
Route::apiResource('users', UserController::class);
Setelah rute diatur, Anda bisa mengakses berbagai endpoint untuk mengelola pengguna:
/api/users
- Mendapatkan semua pengguna/api/users
- Menambahkan pengguna baru/api/users/{id}
- Mendapatkan detail pengguna berdasarkan ID/api/users/{id}
- Memperbarui data pengguna berdasarkan ID/api/users/{id}
- Menghapus pengguna berdasarkan IDUserController
ini menyediakan semua metode CRUD dasar yang Anda butuhkan untuk mengelola pengguna dalam aplikasi Laravel Anda. Dengan menghubungkan controller ini dengan rute yang sesuai, Anda bisa membangun API yang kuat untuk mengelola pengguna.
Pastikan sudah melakukan instalasi CORS
php artisan config:publish cors
Kemudian edit config/cors.php
Contoh kode bisa dilihat di bagian example
Bangun Frontend CSR seperti contoh, kemudian pada bagian controller CategoryController.php ubah menjadi:
/**
* Display a listing of the resource.
*/
/* public function index()
{
return Category::all();
} */
public function index(Request $request)
{
// Tentukan jumlah item per halaman (misalnya 10)
$perPage = 10;
// Ambil kategori dengan pagination
$categories = Category::paginate($perPage);
// Kembalikan data ke frontend dalam format JSON, termasuk informasi pagination
return response()->json([
'data' => $categories->items(), // Data kategori
'current_page' => $categories->currentPage(), // Halaman saat ini
'last_page' => $categories->lastPage(), // Halaman terakhir
'per_page' => $categories->perPage(), // Item per halaman
'total' => $categories->total(), // Total item
'prev_page_url' => $categories->previousPageUrl(), // URL halaman sebelumnya
'next_page_url' => $categories->nextPageUrl(), // URL halaman berikutnya
]);
}
Untuk mendukung search maka kita tinggal tambahkan kondisi jika query search ada di CategoryController.php:
public function index(Request $request)
{
$perPage = 10;
// Ambil nilai pencarian dari query string
$search = $request->input('search');
// Query dasar untuk mendapatkan kategori
$query = Category::query();
// Jika ada nilai pencarian, tambahkan kondisi ke query
if ($search) {
$query->where('name', 'like', '%' . $search . '%')
->orWhere('id', 'like', '%' . $search . '%')
->orWhere('is_publish', 'like', '%' . $search . '%')
->orWhere('created_at', 'like', '%' . $search . '%')
->orWhere('updated_at', 'like', '%' . $search . '%');
}
// Dapatkan hasil query dengan pagination
$categories = $query->paginate($perPage);
// Kembalikan data ke frontend dalam format JSON
return response()->json([
'data' => $categories->items(),
'current_page' => $categories->currentPage(),
'last_page' => $categories->lastPage(),
'per_page' => $categories->perPage(),
'total' => $categories->total(),
'prev_page_url' => $categories->previousPageUrl(),
'next_page_url' => $categories->nextPageUrl(),
]);
}
PASETO (Platform-Agnostic Security Tokens) adalah alternatif yang lebih aman daripada JWT (JSON Web Tokens). Laravel 11 dapat mengimplementasikan PASETO V4 (versi asimetris) untuk autentikasi dengan beberapa langkah sederhana.
Berikut adalah panduan langkah demi langkah untuk mengimplementasikan PASETO V4 di Laravel 11:
Pasang library paragonie/paseto menggunakan Composer. Ini adalah implementasi resmi PASETO untuk PHP.
composer require paragonie/paseto
PASETO V4 menggunakan kunci asimetris, jadi Anda memerlukan sepasang kunci: private (untuk menandatangani token) dan public (untuk memverifikasi token).
Gunakan kode berikut untuk membuat kunci privat dan publik. Anda bisa menyimpannya dalam file .env
atau di database yang aman.
use ParagonIE\Paseto\Keys\AsymmetricSecretKey;
use ParagonIE\Paseto\Protocol\Version4;
// Membuat pasangan kunci privat-publik menggunakan Sodium (libsodium)
$privateKey = AsymmetricSecretKey::generate(new Version4()); // Menghasilkan kunci privat untuk V4
$publicKey = $privateKey->getPublicKey(); // Mengambil kunci publik dari kunci privat
// Encode kunci untuk penyimpanan (Base64)
$privateKeyEncoded = $privateKey->encode();
$publicKeyEncoded = $publicKey->encode();
// Decode kembali kunci privat dan publik dari string yang di-encode
$privateKeyDecoded = AsymmetricSecretKey::fromEncodedString($privateKeyEncoded);
$publicKeyDecoded = $publicKey::fromEncodedString($publicKeyEncoded);
// Tampilkan kunci (untuk tujuan debugging)
echo "Private Key (Encoded): " . $privateKeyEncoded . PHP_EOL;
echo "Public Key (Encoded): " . $publicKeyEncoded . PHP_EOL;
Setelah membuat kunci, simpan di .env
Anda:
PASETO_PRIVATE_KEY=your_private_key_base64
PASETO_PUBLIC_KEY=your_public_key_base64
Middleware digunakan untuk memverifikasi token PASETO setiap kali permintaan datang. Buat middleware baru di Laravel menggunakan perintah artisan:
php artisan make:middleware PasetoAuth
Buka file app/Http/Middleware/PasetoAuth.php
dan tambahkan logika berikut:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use ParagonIE\Paseto\Protocol\Version4;
use ParagonIE\Paseto\Parser;
use ParagonIE\Paseto\Keys\AsymmetricPublicKey;
use ParagonIE\Paseto\Exception\PasetoException;
use ParagonIE\Paseto\Purpose;
use ParagonIE\Paseto\ProtocolCollection;
use Symfony\Component\HttpFoundation\Response;
class PasetoAuth
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
// Ambil token dari header Authorization (Bearer token)
$token = $request->bearerToken();
if (!$token) {
return response()->json(['error' => 'Unauthorized'], Response::HTTP_UNAUTHORIZED);
}
try {
// Ambil kunci publik yang di-encode dari .env
$publicKeyEncoded = env('PASETO_PUBLIC_KEY');
if (!$publicKeyEncoded) {
return response()->json(['error' => 'Public key not found'], 500);
}
// Decode kunci publik
$publicKey = AsymmetricPublicKey::fromEncodedString($publicKeyEncoded);
// Buat koleksi protokol untuk memungkinkan hanya PASETO V4
$protocols = ProtocolCollection::v4();
// Parser untuk memverifikasi token
$parser = (new Parser())
->setPurpose(Purpose::public()) // PASETO V4 adalah token publik
->setKey($publicKey) // Kunci publik untuk verifikasi
->setAllowedVersions($protocols);
// Memverifikasi dan memparse token
$parsedToken = $parser->parse($token);
// Ambil klaim dari token (misalnya user ID)
$claims = $parsedToken->getClaims();
$userId = $claims['sub']; // 'sub' biasanya menyimpan ID pengguna
// Lanjutkan request jika token valid
$request->attributes->set('userId', $userId); // Simpan user ID di request
return $next($request);
} catch (PasetoException $e) {
// Token tidak valid atau gagal diverifikasi
return response()->json(['error' => 'Invalid token: ' . $e->getMessage()], Response::HTTP_UNAUTHORIZED);
}
}
}
Daftarkan middleware ini di bootstrap/app.php
:
use App\Http\Middleware\PasetoAuth;
->withMiddleware(function (Middleware $middleware) {
$middleware->append(PasetoAuth::class);
})
Buat Controller Baru bernama AuthController
php artisan make:controller AuthController
Buat metode di controller untuk menghasilkan token PASETO ketika pengguna login atau melakukan autentikasi.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use ParagonIE\Paseto\Builder;
use ParagonIE\Paseto\Keys\AsymmetricSecretKey;
use ParagonIE\Paseto\Protocol\Version4;
use ParagonIE\Paseto\Purpose;
class AuthController extends Controller
{
public function login(Request $request)
{
// Validasi input login (email dan password)
$credentials = $request->only('email', 'password');
if (auth()->attempt($credentials)) {
$user = auth()->user();
// Ambil kunci privat dari .env dan decode
$privateKeyEncoded = env('PASETO_PRIVATE_KEY');
if (!$privateKeyEncoded) {
return response()->json(['error' => 'Private key not found'], 500);
}
try {
// Decode kunci privat
$privateKey = AsymmetricSecretKey::fromEncodedString($privateKeyEncoded);
// Buat token PASETO
$token = (new Builder())
->setVersion(new Version4()) // Gunakan PASETO V4
->setPurpose(Purpose::public()) // Token publik
->setKey($privateKey) // Kunci privat untuk menandatangani token
->setIssuer('your-app-name') // Issuer aplikasi Anda
->setAudience('your-app-users') // Audience pengguna aplikasi
->setSubject($user->id) // Subjek token adalah ID pengguna
->setExpiration(new \DateTimeImmutable('+1 hour')) // Token berlaku selama 1 jam
->toString();
// Kembalikan token ke frontend
return response()->json(['token' => $token]);
} catch (\Exception $e) {
// Jika gagal menandatangani token
return response()->json(['error' => 'Signing failed: ' . $e->getMessage()], 500);
}
}
return response()->json(['error' => 'Unauthorized'], 401);
}
}
Tambahkan di routes/api.php
use App\Http\Controllers\AuthController;
Route::post('/login', [AuthController::class, 'login']);
Sekarang Anda dapat melindungi route dengan middleware paseto.auth
:
use App\Http\Middleware\PasetoAuth;
Route::apiResource('categories', CategoryController::class)->middleware(PasetoAuth::class);
Di frontend, kirim token PASETO sebagai Bearer token di header Authorization ketika mengakses route yang dilindungi:
fetch('https://example.com/protected-route', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
}
});
untuk mengambil user id dari controller maka kita tinggal memanggil request:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ProtectedController extends Controller
{
public function showProtectedData(Request $request)
{
// Ambil user ID dari atribut request
$userId = $request->get('userId');
// Gunakan user ID sesuai kebutuhan, misalnya untuk mengakses data pengguna
return response()->json([
'message' => 'Protected data accessed',
'userId' => $userId
]);
}
}
Dengan langkah-langkah ini, Anda dapat mengimplementasikan autentikasi menggunakan PASETO V4 di Laravel 11. PASETO menawarkan keamanan yang lebih kuat daripada JWT dengan menggunakan enkripsi asimetris untuk menandatangani dan memverifikasi token.