LaravelProyekAPIMahir6 mnt baca

Proyek: REST API Todo Lengkap

Bangun API todo dari nol: auth Sanctum, CRUD, dan test.

Target Akhir

Di modul ini kamu membangun REST API Todo yang production-grade: register/login mengeluarkan Sanctum token, CRUD todo (title, done) yang hanya bisa diakses pemiliknya, paginasi 10 per halaman, validasi via Form Request, response konsisten via API Resource, dan policy pengunci akses. Selesaikan ini dengan test hijau, dan fondasi API Laravel-mu solid.

Langkah 1: Setup API dan Database

bash
composer create-project laravel/laravel todo-api
cd todo-api
php artisan install:api   # memasang Sanctum + routes/api.php
php artisan make:model Todo -m
php
// database/migrations/xxxx_xx_xx_create_todos_table.php
Schema::create('todos', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained()->cascadeOnDelete();
    $table->string('title', 255);
    $table->boolean('done')->default(false);
    $table->timestamps();
});
php
// app/Models/Todo.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Todo extends Model
{
    protected $fillable = ['title', 'done'];
    protected $casts = ['done' => 'boolean'];

    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

Jalankan php artisan migrate.

Langkah 2: Auth Controller

php
// app/Http/Controllers/Api/AuthController.php
namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;

class AuthController extends Controller
{
    public function register(Request $request)
    {
        $data = $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users',
            'password' => 'required|min:8|confirmed',
        ]);

        $user = User::create([...$data, 'password' => Hash::make($data['password'])]);

        return response()->json([
            'token' => $user->createToken('api')->plainTextToken,
        ], 201);
    }

    public function login(Request $request)
    {
        $data = $request->validate(['email' => 'required|email', 'password' => 'required']);
        $user = User::where('email', $data['email'])->first();

        if (! $user || ! Hash::check($data['password'], $user->password)) {
            return response()->json(['message' => 'Kredensial salah.'], 401);
        }

        return response()->json(['token' => $user->createToken('api')->plainTextToken]);
    }
}

Langkah 3: Form Request dan Resource

php
// app/Http/Requests/StoreTodoRequest.php
public function rules(): array
{
    return ['title' => 'required|string|max:255', 'done' => 'sometimes|boolean'];
}
php
// app/Http/Resources/TodoResource.php
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'title' => $this->title,
        'done' => $this->done,
        'created_at' => $this->created_at->toISOString(),
    ];
}

Langkah 4: Policy dan Controller

bash
php artisan make:policy TodoPolicy --model=Todo
php
// app/Policies/TodoPolicy.php
public function view(User $user, Todo $todo): bool
{
    return $user->id === $todo->user_id;
}
// update() dan delete() polanya identik
php
// app/Http/Controllers/Api/TodoController.php
class TodoController extends Controller
{
    public function index()
    {
        // query via relasi: user mustahil melihat todo orang lain
        return TodoResource::collection(
            auth()->user()->todos()->latest()->paginate(10)
        );
    }

    public function store(StoreTodoRequest $request)
    {
        $todo = auth()->user()->todos()->create($request->validated());

        return new TodoResource($todo);
    }

    public function show(Todo $todo)
    {
        $this->authorize('view', $todo);

        return new TodoResource($todo);
    }

    public function update(StoreTodoRequest $request, Todo $todo)
    {
        $this->authorize('update', $todo);
        $todo->update($request->validated());

        return new TodoResource($todo);
    }

    public function destroy(Todo $todo)
    {
        $this->authorize('delete', $todo);
        $todo->delete();

        return response()->json(null, 204);
    }
}

Ini defense in depth: policy menjaga show/update/destroy, scope relasi menjaga index.

Langkah 5: Routes dan Test Manual

php
// routes/api.php
Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);

Route::middleware('auth:sanctum')->group(function () {
    Route::apiResource('todos', TodoController::class);
});
bash
# register -> simpan tokennya
curl -X POST http://localhost:8000/api/register -H "Content-Type: application/json" \
  -d '{"name":"Budi","email":"[email protected]","password":"rahasia123","password_confirmation":"rahasia123"}'

# buat todo (ganti TOKEN)
curl -X POST http://localhost:8000/api/todos -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" -d '{"title":"Belajar Laravel"}'

# list dengan paginasi
curl http://localhost:8000/api/todos -H "Authorization: Bearer TOKEN"

Checklist Verifikasi

  • Register 201 + token, login salah 401
  • Tanpa token, semua route todo 401
  • User A tidak bisa akses todo user B (403)
  • Title kosong 422 dengan pesan error
  • Response index punya data, links, meta

Catatan teknis: Route::apiResource otomatis menghilangkan route create/edit yang butuh form HTML. Untuk production, tambahkan throttle pada route login untuk menghambat brute force, dan hapus token lama saat login baru agar token tidak menumpuk.

Tantangan

Rancang Dulu

Sebelum coding: tulis daftar endpoint (method + URI + auth + response) untuk API todo di kertas/catatan. Minimal 7 endpoint. Ini melatih API design sebelum implementasi.

Tugas

Tugas: API Todo

Bangun REST API Todo LENGKAP dari nol sesuai spesifikasi modul ini. Kirimkan file-file kuncimu (migration, model, controller, resource, policy, routes/api.php) atau ringkasan endpoint + bukti test Postman. AI tutor akan menilai kelengkapan dan keamanan.

Kriteria penilaian:

  • Semua endpoint CRUD + auth berfungsi
  • Policy: user tidak bisa akses todo milik orang lain
  • Validasi via Form Request, status code tepat
  • Response konsisten via ApiResource + paginasi

AI tutor akan memeriksa bug, kesalahan syntax, dan memberi saran perbaikan.