esign / laravel-linkable
动态链接 Laravel 模型
Requires
- php: ^8.0
- illuminate/database: ^8.0|^9.0|^10.0|^11.0
- illuminate/support: ^8.0|^9.0|^10.0|^11.0
- illuminate/view: ^8.0|^9.0|^10.0|^11.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.5
- orchestra/testbench: ^6.0|^7.0|^8.0|^9.0
- phpunit/phpunit: ^9.0|^10.0
This package is auto-updated.
Last update: 2024-09-12 23:56:46 UTC
README
此包允许您向 Laravel 模型添加动态链接。此动态链接可以指向另一个模型或外部 URL。本质上,这个包只是一个具有额外实用方法的 Laravel 关系。
安装
您可以通过 composer 安装此包
composer require esign/laravel-linkable
用法
准备您的模型
要使模型具有动态链接,您可以添加 HasDynamicLink
特性。
use Esign\Linkable\Concerns\HasDynamicLink; use Illuminate\Database\Eloquent\Model; class MenuItem extends Model { use HasDynamicLink; }
您的数据库结构应如下所示
Schema::create('menu_items', function (Blueprint $table) { $table->id(); $table->string('dynamic_link_type')->nullable(); $table->string('dynamic_link_url')->nullable(); $table->string('dynamic_link_linkable_model')->nullable(); });
内部链接
如果您将 dynamic_link_type
设置为 internal
,则将使用 dynamic_link_linkable_model
字段。为了知道内部动态链接应该指向何处,您可以在相关模型上实现 LinkableUrlContract
。
use Esign\Linkable\Contracts\LinkableUrlContract; class Post extends Model implements LinkableUrlContract { public function linkableUrl(): ?string { return "https:///posts/{$this->id}"; } }
外部链接
如果您将 dynamic_link_type
设置为 external
,则将使用 dynamic_link_url
字段。此字段的值应该是一个有效的 URL,例如 https://www.example.com
。
存储链接
此包提供的是 SingleColumnMorphTo
关系,而不是常规的 MorphTo
关系。一些 CMS(包括我们自己的)不允许基于两列的 morphable 关系,例如 dynamic_link_linkable_type
和 dynamic_link_linkable_id
。SingleColumnMorphTo
将类型和 id 字段合并到单个列中,例如 dynamic_link_linkable_model
。此单列的值存储为 {model}:{id}
格式,例如 post:1
。您可以使用完全限定的类名或来自应用程序的 morph map 的值,就像常规的 morphTo 关系一样。
注意 此方法不是理想的,并且使用此关系进行的某些复杂查询可能无法按预期工作。如果您能够,您可以重写
dynamicLinkLinkable
关系以使用 Laravel 的默认MorphTo
关系。
链接概述
要创建所有可能链接的概述,您可以创建一个 MySQL 视图,该视图创建所有可能链接到的所有可能的模型 联合。
DB::statement(' CREATE OR REPLACE VIEW linkables AS SELECT CONCAT("post:", id) AS id, "post" AS linkable_type, id AS linkable_id, CONCAT("Post - ", title) AS label FROM posts UNION SELECT CONCAT("comment:", id) AS id, "comment" AS linkable_type, id AS linkable_id, CONCAT("Comment - ", title) AS label FROM comments ');
这将生成以下输出
渲染动态链接
此包提供了一个视图组件,可帮助您渲染内部和外部链接。
use Esign\Linkable\Concerns\HasDynamicLink; use App\Models\Post; use App\Models\MenuItem; $post = Post::create(); $menuItemInternal = MenuItem::create([ 'dynamic_link_type' => HasDynamicLink::$linkTypeInternal, 'dynamic_link_url' => null, 'dynamic_link_linkable_model' => "post:{$post->id}", ]); $menuItemExternal = MenuItem::create([ 'dynamic_link_type' => HasDynamicLink::$linkTypeExternal, 'dynamic_link_url' => 'https://www.esign.eu', 'dynamic_link_linkable_model' => null, ]);
当提供类型为 external
的模型时,视图组件将渲染一个 <a>
标签,并应用 target="_blank"
和 rel="noopener"
属性。
<x-linkable-dynamic-link :model="$menuItemInternal">Esign</x-linkable-dynamic-link> <a href="https://www.esign.eu/posts/1">Esign</a>
<x-linkable-dynamic-link :model="$menuItemExternal">Esign</x-linkable-dynamic-link> <a href="https://www.esign.eu" target="_blank" rel="noopener">Esign</a>
扩展此包
创建自己的动态链接类型
此 Laravel 包默认内置了对 内部 和 外部 链接的支持。然而,在某些场景中,您可能希望引入自定义链接类型,例如引用锚点标签。要实现这一点,您可以扩展包的功能。
- 扩展
HasDynamicLink
特性
namespace App\Models\Concerns; use Esign\Linkable\Concerns\HasDynamicLink as BaseHasDynamicLink; trait HasDynamicLink { use BaseHasDynamicLink { dynamicLink as baseDynamicLink; } public static string $linkTypeAnchor = 'anchor'; public function dynamicLink(): ?string { return match ($this->dynamicLinkType()) { static::$linkTypeAnchor => $this->dynamicLinkUrl(), default => $this->baseDynamicLink(), }; } }
- 创建自己的视图组件
接下来,您需要创建自己的视图组件,该组件扩展了包提供的 DynamicLink
组件。以下是实现方法
namespace App\View\Components; use App\Models\Concerns\HasDynamicLink; use Esign\Linkable\View\Components\DynamicLink as BaseDynamicLink; class DynamicLink extends BaseDynamicLink { public function render(): ?View { return match ($this->model->dynamicLinkType()) { HasDynamicLink::$linkTypeAnchor => view('linkable.dynamic-link-anchor'), default => parent::render(), }; } }
<a {{ $attributes->merge(['href' => $model->dynamicLink()]) }}>{{ $slot }}</a>
- 使用自定义视图组件
现在,您可以在 Blade 模板中使用自己的视图组件,而不是包提供的组件
<x-dynamic-link :model="$modelReferencingAnchorTag"> My anchor tag </x-dynamic-link>
测试
composer test
许可证
MIT许可证(MIT)。请参阅许可证文件获取更多信息。