ejunker/laravel-route-attributes

使用PHP属性自动注册路由

1.18.6 2024-09-24 23:46 UTC

This package is auto-updated.

Last update: 2024-09-24 23:47:56 UTC


README

Latest Version on Packagist Tests Type Coverage Total Downloads

此包提供注解来自动注册路由。以下是一个快速示例:

use Spatie\RouteAttributes\Attributes\Get;

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

此属性将自动注册此路由

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

你是视觉学习者吗?

在这个视频中,你将了解PHP 8属性及其在laravel-routes-attributes内部的工作原理。

支持我们

我们投入了大量资源来创建一流的开放源代码包。您可以通过购买我们的付费产品之一来支持我们。

我们非常感谢您从您的家乡给我们寄明信片,并说明您正在使用我们的哪个包。您可以在我们的联系页面上找到我们的地址。我们将在我们的虚拟明信片墙上发布所有收到的明信片。

安装

您可以通过composer安装此包

composer require spatie/laravel-route-attributes

您可以使用以下命令发布配置文件

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

这是已发布配置文件的内容

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

对于应用程序根命名空间目录之外的控制器,也可以使用目录数组中的namespace => path模式添加。以下示例中,将包含来自Modules\Admin\Http\Controllers的控制器。

'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'),
],

用法

该包提供了一些应放在控制器类和方法上的注解。这些注解将用于自动注册路由

添加GET路由

use Spatie\RouteAttributes\Attributes\Get;

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

    }
}

此属性将自动注册此路由

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

使用其他HTTP动词

我们没有遗漏任何HTTP动词。您可以在控制器方法上使用这些属性。

#[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属性。

您可以使用onlyexcept参数来管理您的资源路由的可用性。

您可以使用parameters参数来修改由资源属性设置的默认参数。

您可以使用names参数来设置资源控制器动作的路由名称。传递一个字符串值以设置每个控制器动作的基本路由名称,或传递一个数组值以定义每个控制器动作的路由名称。

您可以使用shallow参数使嵌套资源仅应用于没有唯一子标识符的路由(indexcreatestore)。

您可以使用apiResource布尔参数仅包括用于API的动作。或者,您可以使用扩展Resource属性类的ApiResource属性,但参数apiResource已设置为true

使用Resource属性与DomainPrefixMiddleware属性也是可行的。

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)
    {
    }
}

上述示例中的属性将自动注册以下路由

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');

使用多个动词

要为所有动词注册路由,您可以使用Any属性

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

要一次性注册几个动词的路由,您可以直接使用Route属性。

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

指定路由名称

所有HTTP动词属性都接受一个名为name的参数,该参数接受路由名称。

use Spatie\RouteAttributes\Attributes\Get;

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

此属性将自动注册此路由

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

添加中间件

所有HTTP动词属性都接受一个名为middleware的参数,该参数接受中间件类或中间件类数组。

use Spatie\RouteAttributes\Attributes\Get;

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

    }
}

此注释将自动注册此路由

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

要为类的所有方法应用中间件,您可以使用Middleware属性。您可以将此属性与对方法应用属性混合使用。

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()
    {
    }
}

这些注释将自动注册这些路由

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

指定前缀

您可以在类上使用Prefix注释来为该类所有方法的路由添加前缀。

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()
    {
    }
}

这些注释将自动注册这些路由

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

指定域名

您可以在类上使用Domain注释来为该类所有方法的路由添加前缀。

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()
    {
    }
}

这些注释将自动注册这些路由

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

从配置键指定域名

可能需要从配置文件中定义域名,例如,您的子域名在开发环境中与生产环境不同。

// 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()
    {
    }
}

当解析时,它将从配置文件中获取domains.main的值,并按以下方式注册路由;

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

作用域绑定

在单个路由定义中隐式绑定多个Eloquent模型时,您可能希望将第二个Eloquent模型的作用域限定为必须为前一个Eloquent模型的子模型。
通过添加ScopeBindings注释,您可以启用此行为

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;
    }
}

这类似于手动在路由注册器上使用->scopeBindings()方法

Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
    return $post;
})->scopeBindings();

您还可以在控制器上使用此注释以启用所有方法的隐式作用域绑定。

指定位置

您可以在类或方法上使用Where注释来限制路由参数的格式。

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()
    {
    }
}

这些注释将自动注册这些路由

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]+']);

为了方便起见,一些常用的正则表达式模式有辅助属性,允许您快速将模式约束添加到路由中。

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

指定分组

您可以在类上使用Group注释来为该类所有方法的路由创建具有不同域名和前缀的多个分组。

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()
    {
    }
}

这些注释将自动注册这些路由

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');

指定默认值

您可以在类或方法上使用Defaults注释来定义可选路由参数的默认值。

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)
    {
    }
}

这些注释将自动注册这些路由

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']);

测试

composer test

变更日志

有关最近更改的更多信息,请参阅变更日志

贡献

有关详细信息,请参阅贡献指南

安全漏洞

有关如何报告安全漏洞的信息,请参阅我们的安全策略

致谢

许可证

MIT许可证(MIT)。有关更多信息,请参阅许可证文件