After clone repository install dependencies
composer install
Set Up the Environment
Copy the example .env file and generate the app key:
cp .env.example .env
php artisan key:generate
Run Migrations (if needed)
php artisan migrate
php artisan db:seed
Complete REST API with JWT authentication, role-based access control, and repository pattern
composer require tymon/jwt-auth
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
php artisan jwt:secret
Update config/auth.php
:
'defaults' => [
'guard' => env('AUTH_GUARD', 'api'),
'passwords' => env('AUTH_PASSWORD_BROKER', 'users'),
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
php artisan make:migration create_roles_table
php artisan make:model Role
php artisan make:seeder RoleSeeder
php artisan make:middleware RoleMiddleware
php artisan migrate
php artisan db:seed
POST /api/register
- Register userPOST /api/login
- Login userGET /api/me
- Get current userPOST /api/logout
- Logout user
GET /api/products
- List products (authenticated)GET /api/products/{id}
- Show product (authenticated)POST /api/products
- Create product (admin only)PUT /api/products/{id}
- Update product (admin only)DELETE /api/products/{id}
- Delete product (admin only)
- Register/Login to get JWT token
- Include token in requests:
Authorization: Bearer {token}
- Roles: admin (full access), user (read-only)
Register:
POST /api/register
{
"name": "John Doe",
"email": "john@example.com",
"password": "password",
"role_id": 1
}
Login:
POST /api/login
{
"email": "john@example.com",
"password": "password"
}
php artisan make:migration create_table_name_table
// database/migrations/xxxx_create_table_name_table.php
Schema::create('table_name', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('description')->nullable();
$table->foreignId('related_id')->constrained('related_table');
$table->timestamps();
});
php artisan make:model ModelName
// app/Models/ModelName.php
class ModelName extends Model
{
protected $fillable = ['name', 'description', 'related_id'];
public function related()
{
return $this->belongsTo(RelatedModel::class);
}
}
// app/Repositories/ModelRepositoryInterface.php
interface ModelRepositoryInterface
{
public function all(): Collection;
public function find(int $id): ?ModelName;
public function create(array $data): ModelName;
public function update(int $id, array $data): bool;
public function delete(int $id): bool;
}
// app/Repositories/Impl/ModelRepository.php
class ModelRepository implements ModelRepositoryInterface
{
public function all(): Collection
{
return ModelName::all();
}
public function find(int $id): ?ModelName
{
return ModelName::find($id);
}
public function create(array $data): ModelName
{
return ModelName::create($data);
}
public function update(int $id, array $data): bool
{
$model = ModelName::find($id);
return $model ? $model->update($data) : false;
}
public function delete(int $id): bool
{
$model = ModelName::find($id);
return $model ? $model->delete() : false;
}
}
// app/Services/ModelService.php
class ModelService
{
public function __construct(protected ModelRepositoryInterface $repository) {}
public function getAll(): Collection
{
return $this->repository->all();
}
public function getById(int $id)
{
return $this->repository->find($id);
}
public function create(array $data)
{
return $this->repository->create($data);
}
public function update(int $id, array $data)
{
return $this->repository->update($id, $data);
}
public function delete(int $id)
{
return $this->repository->delete($id);
}
}
php artisan make:controller API/ModelController
// app/Http/Controllers/API/ModelController.php
class ModelController extends Controller
{
public function __construct(protected ModelService $service) {}
public function index()
{
return response()->json($this->service->getAll());
}
public function store(Request $request)
{
$data = $request->validate([
'name' => 'required|string|max:255',
'description' => 'nullable|string',
]);
$model = $this->service->create($data);
return response()->json($model, 201);
}
public function show($id)
{
$model = $this->service->getById($id);
return $model ? response()->json($model) : response()->json(['message' => 'Not Found'], 404);
}
public function update(Request $request, $id)
{
$data = $request->validate([
'name' => 'sometimes|string|max:255',
'description' => 'nullable|string',
]);
$updated = $this->service->update($id, $data);
return $updated ? response()->json(['message' => 'Updated']) : response()->json(['message' => 'Not Found'], 404);
}
public function destroy($id)
{
$deleted = $this->service->delete($id);
return $deleted ? response()->json(['message' => 'Deleted']) : response()->json(['message' => 'Not Found'], 404);
}
}
// app/Providers/AppServiceProvider.php
public function register(): void
{
$this->app->bind(
\App\Repositories\ModelRepositoryInterface::class,
\App\Repositories\Impl\ModelRepository::class
);
}
// routes/api.php
use App\Http\Controllers\API\ModelController;
Route::middleware('api.auth')->group(function () {
Route::get('/models', [ModelController::class, 'index']);
Route::get('/models/{id}', [ModelController::class, 'show']);
Route::middleware('role:admin')->group(function () {
Route::post('/models', [ModelController::class, 'store']);
Route::put('/models/{id}', [ModelController::class, 'update']);
Route::delete('/models/{id}', [ModelController::class, 'destroy']);
});
});
php artisan migrate
- User (with roles)
- Role (admin, user)
- Product
- Course
- Student
- Enrollment
- Authentication:
/api/register
,/api/login
,/api/me
,/api/logout
- Products:
/api/products
(CRUD with role protection) - Courses:
/api/courses
(CRUD with role protection) - Students:
/api/students
(public list, protected CRUD) - Enrollments:
/api/enrollments
(CRUD with role protection)