svanthuijl/laravel-routable-models

这个包允许你创建拥有自己路由的Eloquent模型。

10.0.0 2023-05-23 20:06 UTC

This package is auto-updated.

Last update: 2024-09-24 21:07:03 UTC


README

这个包允许你创建拥有自己路由的Eloquent模型。当模型被保存时,路由会自动生成,并自动在路由器中注册。

本地化路由

这个包还提供了对可翻译模型的本地化路由支持。这是基于 "spatie/laravel-translatable" 构建的。

安装

可以通过Composer安装此包。

composer require svanthuijl/laravel-routable-models

迁移

迁移会自动加载。可选地,你可以使用以下命令发布此包的迁移

php artisan vendor:publish --tag="routable-migrations"

配置

可选地,你可以使用以下命令发布此包的配置文件

php artisan vendor:publish --tag="routable-config"

配置文件被构建为可以与dotenv变量一起配置。

APP_LOCALE=en # This will set the default locale.
APP_LOCALES=en,nl,de #this will set the available locales separated by a comma.

服务提供者

此包的服务提供者不会自动发现。请在config/app.php的服务提供者部分手动注册RoutableServiceProvider。

重要!请确保这是最后一个注册的服务提供者,因为它会检查之前注册的路由。

    'providers' => ServiceProvider::defaultProviders()->merge([
        /*
         * Package Service Providers...
         */

        /*
         * Application Service Providers...
         */

        /*
         * Added last to not be overwritten by application routes...
         */
        Svanthuijl\Routable\RoutableServiceProvider::class,
    ])->toArray(),

使用此包

实现包

要使模型可路由,请实现HasRoutes接口,并在你的模型中使用InteractsWithRoutes特质。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Svanthuijl\Routable\Interfaces\HasRoutes;
use Svanthuijl\Routable\Traits\InteractsWithRoutes;

class Example extends Model implements HasRoutes
{
    use InteractsWithRoutes;
//...

配置路由

通过在你的模型中添加一个registerRoutes方法来配置路由。在这个方法中,你调用$this->addRoute()来创建一个路由。第一个属性是路由名称,第二个是使用的路由生成器。默认名称是default,使用的路由生成器是\Svanthuijl\Routable\DefaultRouteGenerator::class

    /**
     * Defining the routes for this model
     * @return void
     */
    public function registerRoutes(): void
    {
        $this->addRoute()
            ->action('exampleAction')
            ->controller(ExampleController::class);
        $this->addRoute('post')
            ->action('exampleAction')
            ->controller(ExampleController::class)
            ->method('post');
    }

此示例将为每个创建的模型创建两个路由(同一路径上的get和post)。

检索路由

默认路由可以通过路由访问器访问。

$model = new Example();
$model->slug = 'example-001';
$model->save();

$model->route; // Will return (string) "/example-001"
$model->getRoute('post'); // Will return (string) "/example-001/post"

处理路由

此包将自动注册/捕获创建的路由,并将调用配置的动作。模型将作为$model传递给动作。

class ExampleController extends BaseController
{
    public function exampleAction($model): string
    {
        return view('test-view', compact('model'));
    }
}

本地化

此包支持两种类型的本地化路由。

  1. 使用spatie/laravel/translatable为翻译模式提供多个本地化路由
  2. 为具有locale属性的模型前缀单个路由

所有本地化路由都会在路由路径前添加区域设置。

启用包的本地化

通过在dotenv文件中配置APP_LOCALEAPP_LOCALES来启用本地化路由。

APP_LOCALE=en
APP_LOCALES=en,nl

为可翻译模型实现本地化

首先,请确保你已经为你的模型实现了spatie/laravel-translatable。然后,将isTranslatable()添加到路由配置中。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Spatie\Translatable\HasTranslations;
use Svanthuijl\Routable\Interfaces\HasRoutes;
use Svanthuijl\Routable\Traits\InteractsWithRoutes;

class TranslatableExample extends Model implements HasRoutes
{
    use HasTranslations;
    use InteractsWithRoutes;

    /**
     * The attributes that are translatable
     *
     * @var string[]
     */
    public array $translatable = [
        'slug'
    ];

    /**
     * Defining the routes for this model
     * @return void
     */
    public function registerRoutes(): void
    {
        $this->addRoute()
            ->action('exampleAction')
            ->controller(ExampleController::class)
            ->isTranslatable();
    }
//...

使用本地化可翻译路由

现在,将为这个模型创建多个路由。

$model = new TranslatableExample();
$model->slug = [
    'en' => 'slug-in-english',
    'nl' => 'slug-in-dutch',
];
$model->save();

app()->setLocale('en')
$model->route; // Will return (string) "/en/slug-in-english"

app()->setLocale('nl')
$model->route; // Will return (string) "/nl/slug-in-dutch"

$model->getRoute('default', 'en'); // Will return (string) "/en/slug-in-english"
$model->getRoute('default', 'nl'); // Will return (string) "/en/slug-in-dutch"

处理本地化路由

当访问本地化路由时,包将自动设置请求的本地化。

class ExampleController extends BaseController
{
    public function exampleAction($model): string
    {
        app()->locale(); // Will always return the locale for the used route
        return view('test-view', compact('model'));
    }
}

为未翻译模型实现本地化

可以通过在路由生成器上调用isLocalized()来将模型标记为本地化。路由生成器现在期望模型上有一个$locale属性来包含区域设置。属性名称可以通过将参数添加到isLocalized(true, 'my_locale_property')调用中来覆盖。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Svanthuijl\Routable\Interfaces\HasRoutes;
use Svanthuijl\Routable\Traits\InteractsWithRoutes;

class LocalizedExample extends Model implements HasRoutes
{
    use InteractsWithRoutes;

    /**
     * Defining the routes for this model
     * @return void
     */
    public function registerRoutes(): void
    {
        $this->addRoute()
            ->action('exampleAction')
            ->controller(ExampleController::class)
            ->isLocalized();
    }
//...

用法

$model = new LocalizedExample();
$model->locale = 'en';
$model->slug = 'slug-in-english';
$model->save();

$model->route; // Will return (string) "/en/slug-in-english" 

$model = new LocalizedExample();
$model->locale = 'nl';
$model->slug = 'slug-in-dutch';
$model->save();

$model->route; // Will return (string) "/nl/slug-in-dutch" 

在这种情况下,当访问这些路由之一时,app()->locale()将自动设置为适当的区域设置。

禁用路由

可以通过覆盖generateRoutes方法并返回false来禁用特定模型的路由生成。

路由生成器

可以通过下面示例中显示的选项来操作路由。您还可以用您自己的路由生成器替换默认路由生成器,以实现更高级的应用。请确保您的自定义路由生成器类实现了 Svanthuijl\Routable\Interfaces\GeneratesRoutes

    public function registerRoutes(): void
    {
        $this->addRoute('name', Svanthuijl\Routable\DefaultRouteGenerator::class)
            ->action('exampleAction')
            ->controller(ExampleController::class)
            ->fromProperty('slug) // The property to use to generate the route path
            ->isLocalized() // For localized models (cannot be used with isTranslatable)
            ->isTranslatable() // For translatable models (cannot be used with isLocalized)
            ->method('get') // Sets the method the route should listen to
            ->prefix('example') // Prepends the path with "example/"
            ->suffix('example') // Adds "/example" to the path
   }

测试

使用以下命令运行测试:

composer test