PHPackages                             annotation/routing - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. annotation/routing

ActiveLibrary[Framework](/categories/framework)

annotation/routing
==================

Use PHP 8 attributes to register routes in a Laravel Application.

v3.0.0(1mo ago)09.6k1MITPHPPHP ^8.0

Since May 29Pushed 1mo agoCompare

[ Source](https://github.com/dependencies-packagist/routing)[ Packagist](https://packagist.org/packages/annotation/routing)[ Docs](https://github.com/dependencies-packagist/routing)[ RSS](/packages/annotation-routing/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (4)Versions (8)Used By (1)

Laravel Annotation Routing
==========================

[](#laravel-annotation-routing)

Use PHP 8 attributes to register routes in a Laravel Application.

[![GitHub Tag](https://camo.githubusercontent.com/d983d52cddda1f9e19f05c68f3671e215825e4a95c93cb8fe7a76aa91d25305a/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f7461672f646570656e64656e636965732d7061636b61676973742f726f7574696e67)](https://github.com/dependencies-packagist/routing/tagsv)[![Total Downloads](https://camo.githubusercontent.com/fc4efac22f7e1964cd6b19c94281c821304c3be41499d33e23ac279364dbe1ee/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f616e6e6f746174696f6e2f726f7574696e673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/annotation/routing)[![Packagist Version](https://camo.githubusercontent.com/3461369f5350f373ee9a5f5992c81435168e8821d21a43eefd093bfc9532d68c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f616e6e6f746174696f6e2f726f7574696e67)](https://packagist.org/packages/annotation/routing)[![Packagist PHP Version Support](https://camo.githubusercontent.com/1967564ee15423cb4c5ded885b891dd472d041004a5dd07a19a1f09b1603c438/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f616e6e6f746174696f6e2f726f7574696e67)](https://github.com/dependencies-packagist/routing)[![Packagist License](https://camo.githubusercontent.com/8a9240382150083f560866f3228c63a8f68530111a4043088e422253112564b4/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f646570656e64656e636965732d7061636b61676973742f726f7574696e67)](https://github.com/dependencies-packagist/routing)

 Table of Contents1. [Quick Start](#quick-start)
2. [Installation](#installation)
3. [Usage](#usage)
    1. [Basic Usage](#basic-usage)
    2. [Advanced Usage](#advanced-usage)
    3. [Specifying Prefix](#specifying-prefix)
    4. [Specify Named](#specify-named)
    5. [Specifying Middleware](#specifying-middleware)
    6. [Specifying Domain](#specifying-domain)
    7. [Specify Config](#specify-config)
    8. [Specifying ScopeBindings](#specifying-scopeBindings)
    9. [Specifying Where](#specifying-where)
    10. [Specifying Group](#specifying-group)
    11. [Specifying Defaults](#specifying-defaults)
    12. [Specifying WithTrashed](#specifying-withTrashed)
    13. [Specifying Fallback](#specifying-fallback)
4. [Contributing](#contributing)
5. [Contributors](#contributors)
6. [License](#license)

Quick Start
-----------

[](#quick-start)

This package provides attributes to automatically register routes. Here's a quick example:

```
namespace App\Http\Controllers\Backend;

use Annotation\Route\Prefix;

#[Prefix('backend')]
class BaseController extends Controller
{}
```

```
namespace App\Http\Controllers\Backend;

use Annotation\Route\Domain;
use Annotation\Route\Group;
use Annotation\Route\Prefix;
use Annotation\Route\Route\Get;

#[Group(prefix: 'home')]
class HomeController extends BaseController
{
    #[Get('index', 'index')]
    public function index(Request $request)
    {
        //
    }
}
```

This attribute will automatically register this route:

```
use App\Http\Controllers\Backend\HomeController;
use Illuminate\Support\Facades\Route;

Route::prefix('backend/home')
    ->name('backend.home.')
    ->group(function () {
        Route::get('index', [HomeController::class, 'index'])->name('index');
    });
```

Installation
------------

[](#installation)

You can install the package via [Composer](https://getcomposer.org):

```
composer require annotation/routing
```

You can publish the config file with:

```
php artisan vendor:publish --provider="Annotation\Routing\RouteServiceProvider" --tag="config"
```

This is the contents of the published config file:

```
return [

    /*
    |--------------------------------------------------------------------------
    | Automatic Registration Routes
    |--------------------------------------------------------------------------
    |
    | Automatic registration of routes will only happen if this setting is `true`
    |
    */

    'enabled' => true,

    /*
    |--------------------------------------------------------------------------
    | Automatically Registered Paths
    |--------------------------------------------------------------------------
    |
    | Controllers in these directories that have routing attributes will automatically be registered.
    | Optionally, you can specify group configuration by using key/values
    |
    */

    'directories' => [
        app_path('Http/Controllers'),
        app_path('Http/Controllers/Web') => [
            'middleware' => ['web'],
        ],
        app_path('Http/Controllers/Api') => [
            'prefix' => 'api',
            'middleware' => 'api',
        ],
    ],
];
```

\[[back to top](#readme-top)\]

Usage
-----

[](#usage)

The package provides several annotations that should be put on controller classes and methods. These annotations will be used to automatically register routes.

### Basic Usage

[](#basic-usage)

```
namespace App\Http\Controllers;

use Annotation\Route\Route\Get;

class MyController extends Controller
{
    #[Get('route')]
    public function myMethod()
    {
        //
    }
}
```

This attribute will automatically register this route:

```
Route::get('route', [MyController::class, 'myMethod'])->name('my-method');
```

### Advanced Usage

[](#advanced-usage)

`BaseController` has two subclasses: `HomeController` and `AccountController`.

```
namespace App\Http\Controllers\Backend;

use Annotation\Route\Prefix;
use Annotation\Route\Routing\Config;
use App\Http\Controllers\Controller;

#[Prefix('backend')]
#[Config('domains.backend', 'backend.local.dev')]
class BaseController extends Controller
{}
```

#### HomeController:

[](#homecontroller)

```
namespace App\Http\Controllers\Backend;

use Annotation\Route\Prefix;
use Annotation\Route\Route\Get;

#[Prefix('home')]
class HomeController extends BaseController
{
    #[Get]
    public function index(Request $request)
    {
    }
}
```

This attribute will automatically register this route:

```
use App\Http\Controllers\Backend\HomeController;
use Illuminate\Support\Facades\Route;

Route::prefix('backend/home')
    ->name('backend.home.')
    ->domain('backend.local.dev')
    ->group(function () {
        Route::get('index', [HomeController::class, 'index'])->name('index');
    });
```

> Route URI:
>
> Route Named: backend.home.index

#### AccountController:

[](#accountcontroller)

```
namespace App\Http\Controllers\Backend;

use Annotation\Route\Group;
use Annotation\Route\Route\Get;

#[Group(prefix: 'account', domain: 'passport.local.dev', as: 'passport')]
class AccountController extends BaseController
{
    #[Get]
    public function login(Request $request)
    {
    }
}
```

This attribute will automatically register this route:

```
use App\Http\Controllers\Backend\AccountController;
use Illuminate\Support\Facades\Route;

Route::prefix('backend/account')
    ->name('backend.passport.')
    ->group(function () {
        Route::get('login', [AccountController::class, 'login'])->name('login')->domain('passport.local.dev');
    });
```

> Route URI:
>
> Route Named: backend.passport.login

### Specifying Prefix

[](#specifying-prefix)

You can use the `Prefix` annotation on a class to prefix the routes of all methods of that class.

```
namespace App\Http\Controllers;

use Annotation\Route\Prefix;
use Annotation\Route\Route\Get;

#[Prefix('my')]
class MyController
{
    #[Get('route')]
    public function myMethod()
    {
    }
}
```

These annotations will automatically register these routes:

```
Route::get('route', [MyController::class, 'myMethod'])->prefix('my')->name('my.my-method');
```

### Specify Named

[](#specify-named)

All HTTP verb attributes accept a parameter named `name` that accepts a route name.

```
namespace App\Http\Controllers;

use Annotation\Route\Route\Get;

class MyController
{
    #[Get('route', name: 'my-route')]
    public function myMethod()
    {
    }
}
```

This attribute will automatically register this route:

```
Route::get('route', [MyController::class, 'myMethod'])->name('my-route');
```

### Using other HTTP verbs

[](#using-other-http-verbs)

We have left no HTTP verb behind. You can use these attributes on controller methods.

```
#[Annotation\Route\Route\Post('uri')]
#[Annotation\Route\Route\Put('uri')]
#[Annotation\Route\Route\Patch('uri')]
#[Annotation\Route\Route\Delete('uri')]
#[Annotation\Route\Route\Options('uri')]
```

### Using multiple verbs

[](#using-multiple-verbs)

To register a route for all verbs, you can use the `Any` attribute:

```
#[Annotation\Route\Route\Any('uri')]
```

To register a route for a few verbs at once, you can use the `Route` attribute directly:

```
#[Annotation\Route\Route(['put', 'patch'], 'uri')]
```

### Specifying Middleware

[](#specifying-middleware)

All HTTP verb attributes accept a parameter named `middleware` that accepts a middleware class or an array of middleware classes.

```
namespace App\Http\Controllers;

use Annotation\Route\Route\Get;

class MyController
{
    #[Get('route', middleware: MyMiddleware::class)]
    public function myMethod()
    {
    }
}
```

This annotation will automatically register this route:

```
Route::get('route', [MyController::class, 'myMethod'])->middleware(MyMiddleware::class);
```

To apply middleware on all methods of a class you can use the Middleware attribute. You can mix this with applying attribute on a method.

```
namespace App\Http\Controllers;

use Annotation\Route\Route\Get;
use Annotation\Route\Middleware;
use Annotation\Route\WithoutMiddleware;

#[Middleware(GlobalMiddleware::class)]
class MyController
{
    #[Get('route', middleware: MyMiddleware::class)]
    public function myMethod()
    {
    }

    #[Get('global-middleware')]
    public function globalMiddleware()
    {
    }

    #[Get('without-middleware', withoutMiddleware: GlobalMiddleware::class)]
    // or
    // #[WithoutMiddleware(GlobalMiddleware::class)]
    public function withoutMiddleware()
    {
    }
}
```

These annotations will automatically register these routes:

```
Route::get('route', [MyController::class, 'myMethod'])->middleware([GlobalMiddleware::class, MyMiddleware::class]);
Route::get('global-middleware', [MyController::class, 'globalMiddleware'])->middleware(GlobalMiddleware::class);
Route::get('without-middleware', [MyController::class, 'withoutMiddleware']);
```

### Specifying Domain

[](#specifying-domain)

You can use the `Domain` annotation on a class to prefix the routes of all methods of that class.

```
namespace App\Http\Controllers;

use Annotation\Route\Domain;
use Annotation\Route\Route\Get;

#[Domain('subdomain.localhost')]
class MyController
{
    #[Get('route')]
    public function myMethod()
    {
    }
}
```

These annotations will automatically register these routes:

```
Route::get('route', [MyController::class, 'myMethod'])->domain('subdomain.localhost');
```

### Specify Config

[](#specify-config)

There maybe a need to define a domain from a configuration file, for example where your subdomain will be different on your development environment to your production environment.

```
// config/app.php
return [
    'url' => env('APP_URL', 'http://localhost'),
];
```

```
namespace App\Http\Controllers;

use Annotation\Route\Route\Get;
use Annotation\Route\Routing\Config;

#[Config('app.url', '127.0.0.1')]
class MyController
{
    #[Get('route')]
    public function myMethod()
    {
    }
}
```

When this is parsed, it will get the value of `app.url` from the config file and register the route as follows:

```
Route::get('route', [MyController::class, 'myMethod'])->domain('localhost');
```

If `app.url` does not exist and register the route as follows:

```
Route::get('route', [MyController::class, 'myMethod'])->domain('127.0.0.1');
```

### Specifying ScopeBindings

[](#specifying-scopebindings)

When implicitly binding multiple Eloquent models in a single route definition, you may wish to scope the second Eloquent model such that it must be a child of the previous Eloquent model.

By adding the `ScopeBindings` annotation, you can enable this behaviour:

```
namespace App\Http\Controllers;

use Annotation\Route\Route\Get;
use Annotation\Route\ScopeBindings;

class MyController
{
    #[Get('users/{user}/posts/{post}')]
    #[ScopeBindings]
    public function myMethod(User $user, Post $post)
    {
    }
}
```

This is akin to using the `->scopeBindings()` method on the route registrar manually:

```
Route::get('users/{user}/posts/{post}', [MyController::class, 'myMethod'])->scopeBindings();
```

By default, Laravel will enabled scoped bindings on a route when using a custom keyed implicit binding as a nested route parameter, such as `/users/{user}/posts/{post:slug}`.

To disable this behaviour, you can pass `false` to the attribute:

```
#[Annotation\Route\ScopeBindings(false)]
```

This is the equivalent of calling `->withoutScopedBindings()` on the route registrar manually.

You can also use the annotation on controllers to enable implicitly scoped bindings for all its methods. For any methods where you want to override this, you can pass `false` to the attribute on those methods, just like you would normally.

### Specifying Where

[](#specifying-where)

You can use the `Where` annotation on a class or method to constrain the format of your route parameters.

```
namespace App\Http\Controllers;

use Annotation\Route\Route\Get;
use Annotation\Route\Route\Post;
use Annotation\Route\Routing\WhereAlphaNumeric;
use Annotation\Route\Where;

#[Where('custom', '[0-9]+')]
class MyController
{
    #[Get('route/{custom}')]
    public function myMethod()
    {
    }

    #[Post('post-route/{custom}/{alpha-numeric}')]
    #[WhereAlphaNumeric('alpha-numeric')]
    public function myPostMethod()
    {
    }
}
```

These annotations will automatically register these routes:

```
Route::get('route/{custom}', [MyController::class, 'myMethod'])->where(['custom' => '[0-9]+']);
Route::post('post-route/{custom}/{alpha-numeric}', [MyController::class, 'myPostMethod'])->where(['custom' => '[0-9]+', 'alpha-numeric' => '[a-zA-Z0-9]+']);
```

For convenience, some commonly used regular expression patterns have helper attributes that allow you to quickly add pattern constraints to your routes.

```
#[Annotation\Route\Routing\WhereAlpha('alpha')]
#[Annotation\Route\Routing\WhereAlphaNumeric('alpha-numeric')]
#[Annotation\Route\Routing\WhereIn('in', ['value1', 'value2'])]
#[Annotation\Route\Routing\WhereNumber('number')]
#[Annotation\Route\Routing\WhereUlid('ulid')]
#[Annotation\Route\Routing\WhereUuid('uuid')]
```

### Specifying Group

[](#specifying-group)

You can use the `Group` annotation on a class to create multiple groups with different domains and prefixes for the routes of all methods of that class.

```
namespace App\Http\Controllers;

use Annotation\Route\Group;
use Annotation\Route\Route\Get;

#[Group(prefix: 'domain', domain: 'domain.localhost')]
#[Group(prefix: 'subdomain', domain: 'subdomain.localhost')]
class MyController
{
    #[Get('route')]
    public function myMethod()
    {
    }
}
```

These annotations will automatically register these routes:

```
Route::get('route', [MyController::class, 'myMethod'])->prefix('domain')->domain('domain.localhost');
Route::post('route', [MyController::class, 'myMethod'])->prefix('subdomain')->domain('subdomain.localhost');
```

### Specifying Defaults

[](#specifying-defaults)

You can use the `Defaults` annotation on a class or method to define the default values of your optional route parameters.

```
namespace App\Http\Controllers;

use Annotation\Route\Route\Get;
use Annotation\Route\Route\Post;
use Annotation\Route\Routing\Defaults;

#[Defaults('param', 'default')]
class MyController
{
    #[Get('route/{param?}')]
    public function myMethod($param)
    {
    }

    #[Post('route/{param?}/{param2?}')]
    #[Defaults('param2', 'post-default')]
    public function myPostMethod($param, $param2)
    {
    }

    #[Get('override-route/{param?}')]
    #[Defaults('param', 'override-default')]
    public function myOverrideMethod($param)
    {
    }
}
```

These annotations will automatically register these routes:

```
Route::get('route/{param?}', [MyController::class, 'myMethod'])->setDefaults(['param' => 'default']);
Route::post('route/{param?}/{param2?}', [MyController::class, 'myPostMethod'])->setDefaults(['param' => 'default', 'param2' => 'post-default']);
Route::get('override-route/{param?}', [MyController::class, 'myOverrideMethod'])->setDefaults(['param' => 'override-default']);
```

### Specifying WithTrashed

[](#specifying-withtrashed)

- You can use the `WithTrashed` annotation on a class or method to enable WithTrashed bindings to the model.
- You can explicitly override the behaviour using `WithTrashed(false)` if it is applied at the class level.

```
namespace App\Http\Controllers;

use Annotation\Route\Route\Get;
use Annotation\Route\Route\Post;
use Annotation\Route\WithTrashed;

#[WithTrashed]
class MyController
{
    #[Get('route')]
    #[WithTrashed]
    public function myMethod()
    {
    }

    #[Post('route')]
    #[WithTrashed(false)]
    public function myPostMethod()
    {
    }

    #[Get('default-route')]
    public function myDefaultMethod()
    {
    }
}
```

These annotations will automatically register these routes:

```
Route::get('route', [MyController::class, 'myMethod'])->WithTrashed();
Route::post('route', [MyController::class, 'myPostMethod'])->withTrashed(false);
Route::get('default-route', [MyController::class, 'myDefaultMethod'])->withTrashed();
```

### Specifying Fallback

[](#specifying-fallback)

- You can use the `Fallback` annotation on a method that will be executed when no other route matches the incoming request.

```
namespace App\Http\Controllers;

use Annotation\Route\Fallback;

class MyController
{
    #[Fallback]
    public function __invoke(Request $request)
    {
        return '404';
    }
}
```

These annotations will automatically register these routes:

```
Route::fallback(\App\Http\Controllers\MyController::class)->name('fallback');
```

### Resource Controllers

[](#resource-controllers)

To register a [resource controller](https://laravel.com/docs/controllers#resource-controllers), use the `Resource` attribute as shown in the example below.

- You can use `only` or `except` parameters to manage your resource routes availability.
- You can use `parameters` parameter to modify the default parameters set by the resource attribute.
- You can use the `names` parameter to set the route names for the resource controller actions. Pass a string value to set a base route name for each controller action or pass an array value to define the route name for each controller action.
- You can use `shallow` parameter to make a nested resource to apply nesting only to routes without a unique child identifier (`index`, `create`, `store`).
- You can use `apiResource` boolean parameter to only include actions used in APIs. Alternatively, you can use the `ApiResource` attribute, which extends the `Resource` attribute class, but the parameter `apiResource` is already set to `true`.
- Using `Resource` attribute with `Domain`, `Prefix` and `Middleware` attributes works as well.

```
namespace App\Http\Controllers;

use Annotation\Route\Prefix;
use Annotation\Route\Resource;
use Illuminate\Http\Request;

#[Prefix('api/v1')]
#[Resource(
    resource: 'photos.comments',
    apiResource: true,
    except: ['destroy'],
    names: 'photo-comments',
    parameters: ['comments' => 'comment:uuid'],
    shallow: true,
)]
class PhotoCommentController
{
    public function index($photo)
    {}

    public function store(Request $request, $photo)
    {}

    public function show($comment)
    {}

    public function update(Request $request, $comment)
    {}
}
```

The attribute in the example above will automatically register following routes:

```
Route::get('api/v1/comments/{comment}', [PhotoCommentController::class, 'show'])->name('api.v1.photo-comments.show');
Route::match(['put', 'patch'], 'api/v1/comments/{comment}', [PhotoCommentController::class, 'update'])->name('api.v1.photo-comments.update');
Route::get('api/v1/photos/{photo}/comments', [PhotoCommentController::class, 'index'])->name('api.v1.photo-comments.index');
Route::post('api/v1/photos/{photo}/comments', [PhotoCommentController::class, 'store'])->name('api.v1.photo-comments.store');
```

Contributing
------------

[](#contributing)

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

1. Fork the Project
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the Branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request

\[[back to top](#readme-top)\]

Contributors
------------

[](#contributors)

Thanks goes to these wonderful people:

[ ![contrib.rocks image](https://camo.githubusercontent.com/81ad2bcc274b7696b86eb0ea0001a8d369d78ab2226b4c09d2fc8cff33008fb1/68747470733a2f2f636f6e747269622e726f636b732f696d6167653f7265706f3d646570656e64656e636965732d7061636b61676973742f726f7574696e67)](https://github.com/dependencies-packagist/routing/graphs/contributors)Contributions of any kind are welcome!

\[[back to top](#readme-top)\]

License
-------

[](#license)

Distributed under the MIT License (MIT). Please see [License File](https://github.com/dependencies-packagist/routing/blob/main/LICENSE) for more information.

\[[back to top](#readme-top)\]

###  Health Score

43

—

FairBetter than 91% of packages

Maintenance88

Actively maintained with recent releases

Popularity20

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~49 days

Recently: every ~73 days

Total

7

Last Release

59d ago

Major Versions

v1.1.0 → v2.0.02025-06-02

2.x-dev → v3.0.02026-03-20

### Community

Maintainers

![](https://www.gravatar.com/avatar/2da9b458375a1b7972b7c4d26a5bf8f3e48db305e8805da36f253956f33c5568?d=identicon)[jundayw](/maintainers/jundayw)

---

Top Contributors

[![jundayw](https://avatars.githubusercontent.com/u/16873970?v=4)](https://github.com/jundayw "jundayw (51 commits)")

---

Tags

laravelroutingrouteannotationattribute

### Embed Badge

![Health badge](/badges/annotation-routing/health.svg)

```
[![Health](https://phpackages.com/badges/annotation-routing/health.svg)](https://phpackages.com/packages/annotation-routing)
```

###  Alternatives

[pecee/simple-router

Simple, fast PHP router that is easy to get integrated and in almost any project. Heavily inspired by the Laravel router.

696214.6k17](/packages/pecee-simple-router)[laravel-lang/common

Easily connect the necessary language packs to the application

1463.1M22](/packages/laravel-lang-common)[izniburak/router

simple router class for php

23522.6k7](/packages/izniburak-router)[developermarius/simple-router

Simple, fast PHP router that is easy to get integrated and in almost any project. Heavily inspired by the Laravel router.

112.4k](/packages/developermarius-simple-router)[heropoo/routing

A simple and fast route. Use tree structure storage, fast matching!

115.6k1](/packages/heropoo-routing)[ecoal95/php-router

Minimal routing library

271.0k1](/packages/ecoal95-php-router)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
