softmedialabs / laravel-route-annotation
Comprehensive PHP 8 Attribute-based Route Annotation library for Laravel
Package info
github.com/softmedialabs/Laravel-Route-Annotation
pkg:composer/softmedialabs/laravel-route-annotation
Requires
- php: ^8.2|^8.3|^8.4
- illuminate/routing: ^11.0|^12.0|^13.0
- illuminate/support: ^11.0|^12.0|^13.0
- symfony/finder: ^7.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
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.