laravel-route-annotation maintained by softmedialabs
Laravel Route Annotation
Library Laravel modern untuk mendefinisikan routing langsung di controller menggunakan PHP 8 Attributes. Meng-cover seluruh fitur routing bawaan Laravel secara menyeluruh (REST, verbs, middleware, parameter regex constraints, scoping, soft deletes, policy authorization, hingga fallback).
🚀 Fitur Utama
- 100% Fitur Route Laravel Ter-cover: Verbs, Prefix, Domain, Route Name, Middleware, Parameter Constraints (
where), Soft Deletes, Scoped Bindings, dan Defaults. - RESTful & API Resource Controllers: Otomatis mendaftarkan route resource lewat atribut
#[Resource]dan#[ApiResource]. - Kompatibel Penuh dengan Route Cache: Menggunakan referensi controller
[Controller::class, 'method'](tanpa closure), sehingga 100% kompatibel denganphp artisan route:cache. - High Performance Scanner: Mendukung caching metadata scanner secara mandiri (
php artisan route-annotation:cache). - Developer Experience (DX) Bersih: Tidak perlu lagi bolak-balik antara file controller dan
routes/web.php/routes/api.php.
📦 Instalasi
1. Tambahkan ke Proyek
Jika digunakan sebagai paket lokal di proyek Laravel Anda, pastikan path terdaftar di composer.json root aplikasi:
"autoload": {
"psr-4": {
"SoftmediaLabs\\RouteAnnotation\\": "src/route-annotation/src/"
}
}
Jalankan:
composer dump-autoload
2. Registrasi Service Provider (Laravel 11+)
Daftarkan service provider di bootstrap/providers.php:
return [
App\Providers\AppServiceProvider::class,
SoftmediaLabs\RouteAnnotation\RouteAnnotationServiceProvider::class,
];
3. Publish Konfigurasi & AI Agent Guidelines
Publikasikan file konfigurasi config/route-annotation.php:
php artisan vendor:publish --tag=route-annotation-config
Setup untuk AI Agents (Antigravity, Claude Code, Cursor, Boost)
Agar AI agent langsung otomatis paham dan menggunakan Route Annotation saat membuat/mengedit controller (mirip laravel-boost), jalankan:
php artisan route-annotation:install-ai
Command ini secara otomatis:
- Mendeteksi apakah folder
.agents/ada di root proyek; jika belum ada, otomatis dibuat. - Mempublikasikan rules dan index ke
.agents/rules/route-annotation.mddan.agents/rules/index.md. - Menyediakan agent skill di
.agents/skills/route-annotation/SKILL.md. - Meng-update
AGENTS.mddi root proyek (menambahkan instruksi Route Annotation secara aman tanpa me-replace aturan yang sudah ada). (Catatan: folder.ai/hanya berada di level library dan tidak akan mengotori root proyek).
📖 Panduan Penggunaan & Atribut
1. HTTP Verbs Dasar
Pasang atribut pada method controller untuk menentukan metode HTTP dan URI:
use SoftmediaLabs\RouteAnnotation\Attributes\Get;
use SoftmediaLabs\RouteAnnotation\Attributes\Post;
use SoftmediaLabs\RouteAnnotation\Attributes\Put;
use SoftmediaLabs\RouteAnnotation\Attributes\Patch;
use SoftmediaLabs\RouteAnnotation\Attributes\Delete;
use SoftmediaLabs\RouteAnnotation\Attributes\Options;
use SoftmediaLabs\RouteAnnotation\Attributes\Any;
use SoftmediaLabs\RouteAnnotation\Attributes\Route;
use SoftmediaLabs\RouteAnnotation\Attributes\Fallback;
class ArticleController
{
#[Get('/articles', name: 'articles.index')]
public function index() { ... }
#[Post('/articles', name: 'articles.store')]
public function store() { ... }
#[Put('/articles/{id}', name: 'articles.update')]
public function update(int $id) { ... }
#[Patch('/articles/{id}')]
public function patch(int $id) { ... }
#[Delete('/articles/{id}')]
public function destroy(int $id) { ... }
#[Options('/articles')]
public function options() { ... }
#[Any('/webhook')]
public function webhook() { ... }
// Custom multi-methods
#[Route(methods: ['GET', 'POST'], uri: '/contact')]
public function contact() { ... }
// Fallback route
#[Fallback]
public function notFound() { ... }
}
Catatan: Atribut
Routebersifat repeatable, artinya satu method bisa memiliki lebih dari satu route:#[Get('/register/step-1')] #[Post('/register/step-1')] public function stepOne() { ... }
2. Grouping: Prefix, Naming, & Subdomain
Atribut grouping dapat dipasang di level Class Controller (berlaku untuk semua method di controller tersebut) atau di level Method:
use SoftmediaLabs\RouteAnnotation\Attributes\Prefix;
use SoftmediaLabs\RouteAnnotation\Attributes\RouteName;
use SoftmediaLabs\RouteAnnotation\Attributes\Domain;
use SoftmediaLabs\RouteAnnotation\Attributes\Get;
#[Prefix('admin/users', name: 'admin.users.')]
#[Domain('{account}.myapp.com')]
class UserController
{
// URI: {account}.myapp.com/admin/users
// Route name: admin.users.index
#[Get('/', name: 'index')]
public function index() { ... }
// URI: {account}.myapp.com/admin/users/{id}
// Route name: admin.users.show
#[Get('/{id}', name: 'show')]
public function show(int $id) { ... }
}
3. Middleware & Policy Authorization
Gunakan #[Middleware], #[WithoutMiddleware], dan #[Can]:
use SoftmediaLabs\RouteAnnotation\Attributes\Middleware;
use SoftmediaLabs\RouteAnnotation\Attributes\WithoutMiddleware;
use SoftmediaLabs\RouteAnnotation\Attributes\Can;
use SoftmediaLabs\RouteAnnotation\Attributes\Get;
use SoftmediaLabs\RouteAnnotation\Attributes\Delete;
#[Middleware(['auth', 'verified'])]
class DashboardController
{
#[Get('/dashboard')]
public function dashboard() { ... }
// Override: Mengecualikan middleware tertentu
#[Get('/public-stats')]
#[WithoutMiddleware('auth')]
public function publicStats() { ... }
// Shortcut untuk policy authorization (middleware can:delete,post)
#[Delete('/posts/{post}')]
#[Can('delete', 'post')]
public function destroy(Post $post) { ... }
}
4. Parameter Regex Constraints (where)
Library ini menyediakan helper regex parameter yang lengkap:
use SoftmediaLabs\RouteAnnotation\Attributes\Get;
use SoftmediaLabs\RouteAnnotation\Attributes\Where;
use SoftmediaLabs\RouteAnnotation\Attributes\WhereNumber;
use SoftmediaLabs\RouteAnnotation\Attributes\WhereAlpha;
use SoftmediaLabs\RouteAnnotation\Attributes\WhereAlphaNumeric;
use SoftmediaLabs\RouteAnnotation\Attributes\WhereUuid;
use SoftmediaLabs\RouteAnnotation\Attributes\WhereUlid;
use SoftmediaLabs\RouteAnnotation\Attributes\WhereIn;
#[WhereNumber('user_id')] // Dapat dipasang di level class
class ParameterController
{
// Parameter angka: [0-9]+
#[Get('/users/{id}')]
#[WhereNumber('id')]
public function byId(int $id) { ... }
// Parameter huruf: [a-zA-Z]+
#[Get('/tags/{name}')]
#[WhereAlpha('name')]
public function byTag(string $name) { ... }
// Parameter alfanumerik: [a-zA-Z0-9]+
#[Get('/voucher/{code}')]
#[WhereAlphaNumeric('code')]
public function byVoucher(string $code) { ... }
// Parameter UUID standar
#[Get('/orders/{uuid}')]
#[WhereUuid('uuid')]
public function byUuid(string $uuid) { ... }
// Parameter ULID
#[Get('/sessions/{ulid}')]
#[WhereUlid('ulid')]
public function byUlid(string $ulid) { ... }
// Whitelist value (enum-like)
#[Get('/posts/status/{status}')]
#[WhereIn('status', ['draft', 'published', 'archived'])]
public function byStatus(string $status) { ... }
// Custom regex pattern bebas
#[Get('/files/{filename}')]
#[Where('filename', '^[a-z0-9_-]+\.[a-z]{3,4}$')]
public function byFile(string $filename) { ... }
}
5. Model Binding & Fitur Lanjutan
use SoftmediaLabs\RouteAnnotation\Attributes\Get;
use SoftmediaLabs\RouteAnnotation\Attributes\WithTrashed;
use SoftmediaLabs\RouteAnnotation\Attributes\ScopeBindings;
use SoftmediaLabs\RouteAnnotation\Attributes\WithoutScopedBindings;
use SoftmediaLabs\RouteAnnotation\Attributes\Defaults;
class AdvancedController
{
// Mengizinkan soft-deleted model ditemukan di route binding
#[Get('/users/{trashedUser}')]
#[WithTrashed]
public function showTrashed(User $trashedUser) { ... }
// Child model scoped ke parent model
#[Get('/users/{user}/posts/{post}')]
#[ScopeBindings]
public function userPost(User $user, Post $post) { ... }
// Menonaktifkan child model scoping
#[Get('/categories/{category}/posts/{post}')]
#[WithoutScopedBindings]
public function categoryPost(Category $category, Post $post) { ... }
// Nilai default untuk route parameter opsional
#[Get('/items/{category?}')]
#[Defaults(['category' => 'all'])]
public function items(?string $category = null) { ... }
}
6. Resource Controllers
Mendukung otomatisasi RESTful resource controller:
use SoftmediaLabs\RouteAnnotation\Attributes\Resource;
use SoftmediaLabs\RouteAnnotation\Attributes\ApiResource;
use SoftmediaLabs\RouteAnnotation\Attributes\Get;
// Full Web Resource (index, create, store, show, edit, update, destroy)
#[Resource('photos', only: ['index', 'show'])]
class PhotoController
{
public function index() { ... }
public function show(int $id) { ... }
// Anda tetap bisa menambahkan custom action di controller yang sama!
#[Get('/photos/trending', name: 'photos.trending')]
public function trending() { ... }
}
// REST API Resource (tanpa create & edit)
#[ApiResource('api/v1/posts', except: ['destroy'])]
class PostApiController
{
public function index() { ... }
public function store() { ... }
public function show(int $id) { ... }
public function update(int $id) { ... }
}
🛠️ Artisan CLI Commands
| Command | Deskripsi |
|---|---|
php artisan route-annotation:install-ai |
Mempublikasikan panduan AI, memastikan folder .agents/, dan meng-update AGENTS.md. |
php artisan route-annotation:list |
Menampilkan tabel rapi seluruh route & resource yang ditemukan dari anotasi. |
php artisan route-annotation:cache |
Meng-cache hasil scanning controller ke file cache mandiri untuk performa tinggi. |
php artisan route-annotation:clear |
Menghapus file cache anotasi. |
php artisan route:list |
Route bawaan Laravel otomatis menampilkan seluruh route anotasi. |
php artisan route:cache |
Route cache bawaan Laravel otomatis mendukung penuh route anotasi. |
⚙️ Konfigurasi (config/route-annotation.php)
return [
// Status aktivasi route annotation
'enabled' => env('ROUTE_ANNOTATION_ENABLED', true),
// Direktori yang akan di-scan untuk controller
'scan_paths' => [
app_path('Http/Controllers'),
],
// Pola nama file controller
'patterns' => [
'*Controller.php',
],
// File atau folder yang dikecualikan
'excluded_paths' => [
//
],
// Lokasi cache anotasi mandiri
'cache_path' => storage_path('framework/cache/routes-annotation.php'),
];
🧪 Testing
Jalankan test suite library menggunakan PHPUnit:
vendor/bin/phpunit src/route-annotation/tests
Format kode sesuai standar PSR / Laravel Pint:
vendor/bin/pint --format agent src/route-annotation
📄 Lisensi
Library ini dirilis di bawah lisensi MIT.