PHPackages                             spatie/laravel-route-attributes - 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. [API Development](/categories/api)
4. /
5. spatie/laravel-route-attributes

ActiveLibrary[API Development](/categories/api)

spatie/laravel-route-attributes
===============================

Auto register routes using PHP attributes

1.28.0(2mo ago)879963.2k↑18%87[1 PRs](https://github.com/spatie/laravel-route-attributes/pulls)15MITPHPPHP ^8.3CI passing

Since Oct 28Pushed 1mo ago11 watchersCompare

[ Source](https://github.com/spatie/laravel-route-attributes)[ Packagist](https://packagist.org/packages/spatie/laravel-route-attributes)[ Docs](https://github.com/spatie/laravel-route-attributes)[ GitHub Sponsors](https://github.com/sponsors/spatie)[ Fund](https://spatie.be/open-source/support-us)[ RSS](/packages/spatie-laravel-route-attributes/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (14)Versions (57)Used By (15)

Use PHP 8 attributes to register routes in a Laravel app
========================================================

[](#use-php-8-attributes-to-register-routes-in-a-laravel-app)

[![Latest Version on Packagist](https://camo.githubusercontent.com/a0c99854bd22e8df70b2af98612f082bd18789e7cfef06ac8bc323789587b79a/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7370617469652f6c61726176656c2d726f7574652d617474726962757465732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spatie/laravel-route-attributes)[![Tests](https://github.com/spatie/laravel-route-attributes/workflows/Tests/badge.svg)](https://github.com/spatie/laravel-route-attributes/workflows/Tests/badge.svg)[![Type Coverage](https://camo.githubusercontent.com/2948d9bc332bd7f0753afcba62bb81f049f5308352d2ac01ec3192b2ddee038b/68747470733a2f2f73686570686572642e6465762f6769746875622f7370617469652f6c61726176656c2d726f7574652d617474726962757465732f636f7665726167652e737667)](https://shepherd.dev/github/spatie/laravel-route-attributes)[![Total Downloads](https://camo.githubusercontent.com/191af57004c89bd2f0adbeae76ae0995e63b48608ea658f8ac1f5ddcec4f2699/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7370617469652f6c61726176656c2d726f7574652d617474726962757465732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spatie/laravel-route-attributes)

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

```
use Spatie\RouteAttributes\Attributes\Get;

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

This attribute will automatically register this route:

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

Are you a visual learner?
-------------------------

[](#are-you-a-visual-learner)

[In this video](https://spatie.be/videos/front-line-php/adding-meta-data-using-attributes) you'll get an introduction to PHP 8 attributes and how this laravel-routes-attributes works under the hood.

Support us
----------

[](#support-us)

[![](https://camo.githubusercontent.com/f1310a5a220f080a1646d5f1b2e5bd61ab81e8d9497d06c2a460a7d2f49bd107/68747470733a2f2f6769746875622d6164732e73332e65752d63656e7472616c2d312e616d617a6f6e6177732e636f6d2f6c61726176656c2d726f7574652d617474726962757465732e6a70673f743d32)](https://spatie.be/github-ad-click/laravel-route-attributes)

We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us).

We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards).

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

[](#installation)

You can install the package via composer:

```
composer require spatie/laravel-route-attributes
```

You can publish the config file with:

```
php artisan vendor:publish --provider="Spatie\RouteAttributes\RouteAttributesServiceProvider" --tag="config"
```

This is the contents of the published config file:

```
return [
    /*
     *  Automatic registration of routes will only happen if this setting is `true`
     */
    'enabled' => true,

    /*
     * 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'
        ],
    ],
];
```

For controllers outside the applications root namespace directories can also be added using a `namespace => path` pattern in the directories array. In the following example controllers from `Modules\Admin\Http\Controllers` will be included.

```
'directories' => [
    'Modules\Admin\Http\Controllers\\' => base_path('admin-module/Http/Controllers'),
    // Or
    base_path('admin-module/Http/Controllers') => [
        'namespace' => 'Modules\Admin\Http\Controllers\\'
    ],
    app_path('Http/Controllers'),
],
```

If you are using a directory structure where you co-locate multiple types of files in the same directory and want to be more specific about which files are checked for route attributes, you can use the `patterns` and `not_patterns`options. For example, if you are co-locating your tests with your controllers you could use the `patterns` option to only look in controller files, or you could use `not_patterns` to configure it to not look in test files for route attributes.

```
'directories' => [
    base_path('app-modules/Blog') => [
        // only register routes in files that match the patterns
        'patterns' => ['*Controller.php'],
        // do not register routes in files that match the patterns
        'not_patterns' => ['*Test.php'],
    ],
],
```

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

### Adding a GET route

[](#adding-a-get-route)

```
use Spatie\RouteAttributes\Attributes\Get;

class MyController
{
    #[Get('my-route')]
    public function myMethod()
    {

    }
}
```

This attribute will automatically register this route:

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

### Using other HTTP verbs

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

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

```
#[Spatie\RouteAttributes\Attributes\Post('my-uri')]
#[Spatie\RouteAttributes\Attributes\Put('my-uri')]
#[Spatie\RouteAttributes\Attributes\Patch('my-uri')]
#[Spatie\RouteAttributes\Attributes\Delete('my-uri')]
#[Spatie\RouteAttributes\Attributes\Options('my-uri')]
```

### 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.

```
use Spatie\RouteAttributes\Attributes\Resource;

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

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

    public function show(Comment $comment)
    {
    }

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

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

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

### Using multiple verbs

[](#using-multiple-verbs)

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

```
#[Spatie\RouteAttributes\Attributes\Any('my-uri')]
```

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

```
#[Spatie\RouteAttributes\Attributes\Route(['put', 'patch'], 'my-uri')]
```

### Specify a route name

[](#specify-a-route-name)

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

```
use Spatie\RouteAttributes\Attributes\Get;

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

This attribute will automatically register this route:

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

### Adding middleware

[](#adding-middleware)

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

```
use Spatie\RouteAttributes\Attributes\Get;

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

    }
}
```

This annotation will automatically register this route:

```
Route::get('my-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.

```
use Spatie\RouteAttributes\Attributes\Get;
use Spatie\RouteAttributes\Attributes\Middleware;

#[Middleware(MyMiddleware::class)]
class MyController
{
    #[Get('my-route')]
    public function firstMethod()
    {
    }

    #[Get('my-other-route', middleware: MyOtherMiddleware::class)]
    public function secondMethod()
    {
    }
}
```

These annotations will automatically register these routes:

```
Route::get('my-route', [MyController::class, 'firstMethod'])->middleware(MyMiddleware::class);
Route::get('my-other-route', [MyController::class, 'secondMethod'])->middleware([MyMiddleware::class, MyOtherMiddleware::class]);
```

### Specifying a prefix

[](#specifying-a-prefix)

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

```
use Spatie\RouteAttributes\Attributes\Get;
use Spatie\RouteAttributes\Attributes\Post;
use Spatie\RouteAttributes\Attributes\Prefix;

#[Prefix('my-prefix')]
class MyController
{
    #[Get('my-get-route')]
    public function myGetMethod()
    {
    }

    #[Post('my-post-route')]
    public function myPostMethod()
    {
    }
}
```

These annotations will automatically register these routes:

```
Route::get('my-prefix/my-get-route', [MyController::class, 'myGetMethod']);
Route::post('my-prefix/my-post-route', [MyController::class, 'myPostMethod']);
```

### Specifying a domain

[](#specifying-a-domain)

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

```
use Spatie\RouteAttributes\Attributes\Get;
use Spatie\RouteAttributes\Attributes\Post;
use Spatie\RouteAttributes\Attributes\Domain;

#[Domain('my-subdomain.localhost')]
class MyController
{
    #[Get('my-get-route')]
    public function myGetMethod()
    {
    }

    #[Post('my-post-route')]
    public function myPostMethod()
    {
    }
}
```

These annotations will automatically register these routes:

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

### Specifying a domain from a config key

[](#specifying-a-domain-from-a-config-key)

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/domains.php
return [
    'main' => env('SITE_URL', 'example.com'),
    'subdomain' => env('SUBDOMAIN_URL', 'subdomain.example.com')
];
```

```
use Spatie\RouteAttributes\Attributes\Get;
use Spatie\RouteAttributes\Attributes\Post;
use Spatie\RouteAttributes\Attributes\DomainFromConfig;

#[DomainFromConfig('domains.main')]
class MyController
{
    #[Get('my-get-route')]
    public function myGetMethod()
    {
    }
}
```

When this is parsed, it will get the value of `domains.main` from the config file and register the route as follows;

```
Route::get('my-get-route', [MyController::class, 'myGetMethod'])->domain('example.com');
```

### Scoping bindings

[](#scoping-bindings)

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:

```
use Spatie\RouteAttributes\Attributes\Get;
use Spatie\RouteAttributes\Attributes\ScopeBindings;

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

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

```
Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
    return $post;
})->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:

```
#[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.

```
use Spatie\RouteAttributes\Attributes\Get;
use Spatie\RouteAttributes\Attributes\Post;
use Spatie\RouteAttributes\Attributes\Where;
use Spatie\RouteAttributes\Attributes\WhereAlphaNumeric;

#[Where('my-where', '[0-9]+')]
class MyController
{
    #[Get('my-get-route/{my-where}')]
    public function myGetMethod()
    {
    }

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

These annotations will automatically register these routes:

```
Route::get('my-get-route/{my-where}', [MyController::class, 'myGetMethod'])->where(['my-where' => '[0-9]+']);
Route::post('my-post-route/{my-where}/{my-alpha-numeric}', [MyController::class, 'myPostMethod'])->where(['my-where' => '[0-9]+', 'my-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.

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

### Specifying a group

[](#specifying-a-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.

```
use Spatie\RouteAttributes\Attributes\Get;
use Spatie\RouteAttributes\Attributes\Post;
use Spatie\RouteAttributes\Attributes\Domain;

#[Group(domain: 'my-subdomain.localhost', prefix: 'my-prefix')]
#[Group(domain: 'my-second-subdomain.localhost', prefix: 'my-second-prefix')]
class MyController
{
    #[Get('my-get-route')]
    public function myGetMethod()
    {
    }

    #[Post('my-post-route')]
    public function myPostMethod()
    {
    }
}
```

These annotations will automatically register these routes:

```
Route::get('my-get-route', [MyController::class, 'myGetMethod'])->prefix('my-prefix')->domain('my-subdomain.localhost');
Route::post('my-post-route', [MyController::class, 'myPostMethod'])->prefix('my-prefix')->domain('my-subdomain.localhost');
Route::get('my-get-route', [MyController::class, 'myGetMethod'])->prefix('my-second-prefix')->domain('my-second-subdomain.localhost');
Route::post('my-post-route', [MyController::class, 'myPostMethod'])->prefix('my-second-prefix')->domain('my-second-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.

```
use Spatie\RouteAttributes\Attributes\Defaults;
use Spatie\RouteAttributes\Attributes\Get;
use Spatie\RouteAttributes\Attributes\Post;

#[Defaults('param', 'controller-default')]
class MyController extends Controller
{
    #[Get('my-get-route/{param?}')]
    public function myGetMethod($param)
    {
    }

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

    #[Get('my-default-route/{param?}/{param2?}/{param3?}')]
    #[Defaults('param2', 'method-default-first')]
    #[Defaults('param3', 'method-default-second')]
    public function myDefaultMethod($param, $param2, $param3)
    {
    }

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

These annotations will automatically register these routes:

```
Route::get('my-get-route/{param?}', [MyController::class, 'myGetMethod'])->setDefaults(['param', 'controller-default']);
Route::post('my-post-route/{param?}/{param2?}', [MyController::class, 'myPostMethod'])->setDefaults(['param', 'controller-default', 'param2' => 'method-default']);
Route::get('my-default-route/{param?}/{param2?}/{param3?}', [MyController::class, 'myDefaultMethod'])->setDefaults(['param', 'controller-default', 'param2' => 'method-default-first', 'param3' => 'method-default-second']);
Route::get('my-override-route/{param?}', [MyController::class, 'myOverrideMethod'])->setDefaults(['param', 'method-default']);
```

### With Trashed

[](#with-trashed)

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

```
use Spatie\RouteAttributes\Attributes\Get;
use Spatie\RouteAttributes\Attributes\Post;
use Spatie\RouteAttributes\Attributes\WithTrashed;

#[WithTrashed]
class MyController extends Controller
{
    #[Get('my-get-route/{param}')]
    #[WithTrashed]
    public function myGetMethod($param)
    {
    }

    #[Post('my-post-route/{param}')]
    #[WithTrashed(false)]
    public function myPostMethod($param)
    {
    }

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

These annotations will automatically register these routes:

```
Route::get('my-get-route/{param}', [MyController::class, 'myGetMethod'])->WithTrashed();
Route::post('my-post-route/{param}', [MyController::class, 'myPostMethod'])->withTrashed(false);
Route::get('my-default-route/{param}', [MyController::class, 'myDefaultMethod'])->withTrashed();
```

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

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

[](#contributing)

Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Freek Van der Herten](https://github.com/freekmurze)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

72

—

ExcellentBetter than 100% of packages

Maintenance88

Actively maintained with recent releases

Popularity63

Solid adoption and visibility

Community41

Growing community involvement

Maturity82

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 57.5% 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 ~39 days

Recently: every ~25 days

Total

51

Last Release

74d ago

Major Versions

0.0.1 → 1.0.02020-10-29

PHP version history (3 changes)0.0.1PHP ^8.0

1.26.0PHP ^8.2

1.27.0PHP ^8.3

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/7535935?v=4)[Spatie](/maintainers/spatie)[@spatie](https://github.com/spatie)

---

Top Contributors

[![freekmurze](https://avatars.githubusercontent.com/u/483853?v=4)](https://github.com/freekmurze "freekmurze (239 commits)")[![osbre](https://avatars.githubusercontent.com/u/23292709?v=4)](https://github.com/osbre "osbre (15 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (15 commits)")[![patinthehat](https://avatars.githubusercontent.com/u/5508707?v=4)](https://github.com/patinthehat "patinthehat (12 commits)")[![Tofandel](https://avatars.githubusercontent.com/u/6115458?v=4)](https://github.com/Tofandel "Tofandel (12 commits)")[![robertdrakedennis](https://avatars.githubusercontent.com/u/31261583?v=4)](https://github.com/robertdrakedennis "robertdrakedennis (10 commits)")[![giorgiopogliani](https://avatars.githubusercontent.com/u/28866565?v=4)](https://github.com/giorgiopogliani "giorgiopogliani (9 commits)")[![Radiergummi](https://avatars.githubusercontent.com/u/6115429?v=4)](https://github.com/Radiergummi "Radiergummi (9 commits)")[![midnite81](https://avatars.githubusercontent.com/u/254850?v=4)](https://github.com/midnite81 "midnite81 (8 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (8 commits)")[![leonardocaldas](https://avatars.githubusercontent.com/u/17347635?v=4)](https://github.com/leonardocaldas "leonardocaldas (8 commits)")[![danielsetreus](https://avatars.githubusercontent.com/u/2234052?v=4)](https://github.com/danielsetreus "danielsetreus (7 commits)")[![Nielsvanpach](https://avatars.githubusercontent.com/u/10651054?v=4)](https://github.com/Nielsvanpach "Nielsvanpach (7 commits)")[![sirmathays](https://avatars.githubusercontent.com/u/37704147?v=4)](https://github.com/sirmathays "sirmathays (7 commits)")[![serkanerip](https://avatars.githubusercontent.com/u/8780913?v=4)](https://github.com/serkanerip "serkanerip (6 commits)")[![jaulz](https://avatars.githubusercontent.com/u/5358638?v=4)](https://github.com/jaulz "jaulz (5 commits)")[![laravel-shift](https://avatars.githubusercontent.com/u/15991828?v=4)](https://github.com/laravel-shift "laravel-shift (5 commits)")[![brendt](https://avatars.githubusercontent.com/u/6905297?v=4)](https://github.com/brendt "brendt (4 commits)")[![asharifineyestani](https://avatars.githubusercontent.com/u/12456855?v=4)](https://github.com/asharifineyestani "asharifineyestani (4 commits)")[![AdrianMrn](https://avatars.githubusercontent.com/u/12762044?v=4)](https://github.com/AdrianMrn "AdrianMrn (4 commits)")

---

Tags

laravelphpphp8spatielaravel-route-attributes

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/spatie-laravel-route-attributes/health.svg)

```
[![Health](https://phpackages.com/badges/spatie-laravel-route-attributes/health.svg)](https://phpackages.com/packages/spatie-laravel-route-attributes)
```

###  Alternatives

[spatie/laravel-fractal

An easy to use Fractal integration for Laravel applications

1.9k15.1M99](/packages/spatie-laravel-fractal)[spatie/laravel-responsecache

Speed up a Laravel application by caching the entire response

2.8k8.2M51](/packages/spatie-laravel-responsecache)[spatie/laravel-honeypot

Preventing spam submitted through forms

1.6k6.0M60](/packages/spatie-laravel-honeypot)[spatie/laravel-route-discovery

Auto register routes using PHP attributes

23645.0k2](/packages/spatie-laravel-route-discovery)[spatie/laravel-markdown-response

Serve markdown versions of your HTML pages to AI agents and bots

6512.6k](/packages/spatie-laravel-markdown-response)[spatie/spatie-price-api

The Price API used at promotional sites for our own products

1515.1k1](/packages/spatie-spatie-price-api)

PHPackages © 2026

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