laravelapiproyekrestMahir4 mnt baca
Proyek Mini: Todo REST API
Bangun API todo lengkap dari nol: migration, model, resource, controller, dan route API.
Rencana project
Kita gabungkan semua modul API jadi satu project nyata: Todo REST API dengan autentikasi Sanctum. Endpoint: list, buat, lihat, update, hapus, dan toggle selesai. Ini fondasi yang dipakai hampir semua API mobile.
Langkah 1: migration dan model
bash
php artisan make:migration create_todos_table
php artisan make:model Todophp
// database/migrations/xxxx_create_todos_table.php
Schema::create('todos', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('judul');
$table->text('deskripsi')->nullable();
$table->boolean('selesai')->default(false);
$table->timestamps();
});php
// app/Models/Todo.php
class Todo extends Model
{
protected $fillable = ['judul', 'deskripsi', 'selesai'];
protected function casts(): array
{
return ['selesai' => 'boolean'];
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}Langkah 2: resource dan request
bash
php artisan make:resource TodoResource
php artisan make:request StoreTodoRequestphp
// app/Http/Resources/TodoResource.php
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'judul' => $this->judul,
'deskripsi' => $this->deskripsi,
'selesai' => $this->selesai,
'dibuat' => $this->created_at->diffForHumans(),
];
}Langkah 3: controller dan route
php
// app/Http/Controllers/Api/TodoController.php
class TodoController extends Controller
{
public function index(Request $request)
{
$todos = $request->user()->todos()->latest()->paginate(15);
return TodoResource::collection($todos);
}
public function store(StoreTodoRequest $request)
{
$todo = $request->user()->todos()->create($request->validated());
return (new TodoResource($todo))->response()->setStatusCode(201);
}
public function update(StoreTodoRequest $request, Todo $todo)
{
Gate::authorize('update', $todo);
$todo->update($request->validated());
return new TodoResource($todo);
}
public function destroy(Todo $todo)
{
Gate::authorize('delete', $todo);
$todo->delete();
return response()->noContent();
}
public function toggle(Todo $todo)
{
Gate::authorize('update', $todo);
$todo->update(['selesai' => ! $todo->selesai]);
return new TodoResource($todo);
}
}php
// routes/api.php
Route::middleware('auth:sanctum')->group(function () {
Route::apiResource('todos', TodoController::class);
Route::patch('todos/{todo}/toggle', [TodoController::class, 'toggle']);
});Langkah 4: uji dengan curl
bash
# Buat token dulu lewat login, lalu:
curl -H "Authorization: Bearer TOKENMU" \
-H "Accept: application/json" \
http://127.0.0.1:8000/api/todos
curl -X POST -H "Authorization: Bearer TOKENMU" \
-H "Accept: application/json" -H "Content-Type: application/json" \
-d '{"judul":"Belajar Laravel","deskripsi":"Sampai mahir"}' \
http://127.0.0.1:8000/api/todosCatatan teknis: Route model binding
{todo}mengambil todo milik SIAPA SAJA berdasarkan ID. TanpaGate::authorize, user A bisa mengupdate todo milik user B hanya dengan menebak ID. Selalu pasang policy atau tambahkan scopewhere('user_id', auth()->id())di binding. Keamanan tidak boleh mengandalkan "ID kan susah ditebak".