danilogiacomi / filament-nested-resources
Requires
- filament/filament: ^3.0.0
- livewire/livewire: ^3.0
- spatie/laravel-package-tools: ^1.15
Requires (Dev)
- filament/spatie-laravel-translatable-plugin: ^3.2
- laravel/pint: ^1.11
- orchestra/testbench: ^8.0
This package is auto-updated.
Last update: 2024-09-24 15:30:27 UTC
README
Filament Nested Resources
Filament Nested Resources 允许您创建任何深度的嵌套资源。这对于过于复杂而无法作为独立资源使用的关系管理器来说很有用。
首次公开发布在此。
展示
支持我们
您的支持对我们插件持续进步至关重要。我们感谢迄今为止所有为我们的旅程做出贡献的用户。
虽然我们的插件对所有用户都可用,但如果您正在将其用于商业目的,并认为它为您的事业增添了显著价值,我们诚恳地请求您考虑通过 GitHub Sponsors 支持我们。这种赞助将帮助我们持续开发和维护,以保持插件强大且最新。您捐赠的任何金额都将极大地帮助我们实现目标。加入我们,使这个插件变得更好,并推动进一步的创新。
安装
您可以通过 composer 安装此包
composer require guava/filament-nested-resources
用法
在整个文档中,我引用了 root
嵌套资源和 child
嵌套资源。唯一的区别是 Root
是关系树中的第一个资源。
在示例中:ArtistResource > AlbumResource > SongResource
Artist 将是根资源,其他则是子资源。
支持的关系
目前我们仅支持 一对一 和 多态一对一 关系。
演示项目
为了更好地了解嵌套资源的工作原理以及解决您可能遇到的问题,我们创建了一个演示 Laravel 项目:[https://github.com/GuavaCZ/filament-nested-resources-demo](https://github.com/GuavaCZ/filament-nested-resources-demo)
快速入门
为了设置嵌套资源,您需要执行以下步骤
- 在您想要嵌套的资源(根和所有子资源)上,添加
NestedResource
特性。您需要实现getAncestor
方法。对于根资源,返回null
,对于所有子资源,根据以下文档实现它。 - 在第一步中资源的每个页面上,添加
NestedPage
特性。 - 创建一个
RelationManager
([Filament 文档](https://filamentphp.com/docs/3.x/panels/resources/relation-managers#creating-a-relation-manager))或一个RelationPage
([Filament 文档](https://filamentphp.com/docs/3.x/panels/resources/relation-managers#relation-pages))来绑定资源。将NestedRelationManager
特性添加到其中任何一个。
让我们想象一下展示截图中的场景,其中我们具有这个模式
- Artist 模型。
- Album 模型(属于 Artist)。
- Song 模型(属于 Album)。
首先我们创建 ArtistResource
use Filament\Resources\Resource; use Guava\FilamentNestedResources\Concerns\NestedResource; class ArtistResource extends Resource { use NestedResource; // If using Relation Manager: public static function getRelations(): array { return [ AlbumsRelationManager::class, ]; } public static function getPages(): array { return [ 'index' => Pages\ListArtists::route('/'), 'create' => Pages\CreateArtist::route('/create'), 'edit' => Pages\EditArtist::route('/{record}/edit'), 'view' => Pages\ViewArtist::route('/{record}'), // In case of relation page. // Make sure the name corresponds to the name of your actual relationship on the model. 'albums' => Pages\ManageArtistAlbums::route('/{record}/albums'), // Needed to create child records // The name should be '{relationshipName}.create': 'albums.create' => Pages\CreateArtistAlbum::route('/{record}/albums/create'), ]; } public static function getAncestor(): ?Ancestor { return null; } }
接下来,我们创建 AlbumResource
use Filament\Resources\Resource; use Guava\FilamentNestedResources\Concerns\NestedResource; class AlbumResource extends Resource { use NestedResource; public static function getRelations(): array { return [ // Repeat the same for Song Resource ]; } public static function getAncestor() : ?Ancestor { // Configure the ancestor (parent) relationship here return Ancestor::make( 'albums', // Relationship name 'artist', // Inverse relationship name ); } }
在 ArtistResource
和 AlbumResource
的每个页面上,我们添加 NestedPage
特性
use Filament\Resources\Pages\CreateRecord; use Guava\FilamentNestedResources\Concerns\NestedPage; class CreateArtist extends CreateRecord { use NestedPage; // }
use Filament\Resources\Pages\EditRecord; use Guava\FilamentNestedResources\Concerns\NestedPage; class EditArtist extends EditRecord { use NestedPage; // }
use Filament\Resources\Pages\ListRecords; use Guava\FilamentNestedResources\Concerns\NestedPage; class ListArtists extends ListRecords { use NestedPage; // }
现在让我们创建一个新的页面,它将用于创建子记录。在 ArtistResource/Pages
中创建 CreateArtistAlbum
页面
use Guava\FilamentNestedResources\Pages\CreateRelatedRecord; use Guava\FilamentNestedResources\Concerns\NestedPage; class CreateArtistAlbum extends CreateRelatedRecord { use NestedPage; // This page also needs to know the ancestor relationship used (just like relation managers): protected static string $relationship = 'albums'; // We can usually guess the nested resource, but if your app has multiple resources for this // model, you will need to explicitly define it // public static string $nestedResource = AlbumResource::class; }
别忘了在 getPages
方法中注册页面。
最后,我们创建 AlbumsRelationManager
或如果您更喜欢使用关系页面,则创建 ManageArtistAlbums
页面。我们只需要在这里添加 NestedRelationManager
特性。
针对RelationManager
use Filament\Resources\RelationManagers\RelationManager; use Guava\FilamentNestedResources\Concerns\NestedRelationManager; class AlbumsRelationManager extends RelationManager { use NestedRelationManager; // We can usually guess the nested resource, but if your app has multiple resources for this // model, you will need to explicitly define the it // public static string $nestedResource = AlbumResource::class; }
针对RelationPage
use Filament\Resources\Pages\ManageRelatedRecords; use Guava\FilamentNestedResources\Concerns\NestedPage; use Guava\FilamentNestedResources\Concerns\NestedRelationManager; class ManageArtistAlbums extends ManageRelatedRecords { use NestedPage; // Since this is a standalone page, we also need this trait use NestedRelationManager; // }
可选,我们建议从您的子NestedResources
(在这种情况下为AlbumResource)中删除index
和create
页面。
定制面包屑
每个资源都可以控制自己的面包屑部分,默认由一个index
面包屑和一个detail
面包屑组成。
index
面包屑通常重定向到索引页面。
detail
面包屑通常重定向到详细(编辑或查看)页面,默认情况下将显示记录的路由键(如果没有配置则为ID)。
您可以通过NestedResource
的getBreadcrumbRecordLabel
方法覆盖标签
public static function getBreadcrumbRecordLabel(Model $record) { return $record->first_name . ' ' . $record->last_name; }
或者,您可以通过在资源上重写getBreadcrumbs
方法来完全覆盖资源的面包屑部分
public static function getBreadcrumbs(Model $record, string $operation): array { return [ 'my-custom-url' => 'My custom label', ]; }
贡献
请参阅CONTRIBUTING以获取详细信息。
安全漏洞
请审查我们关于如何报告安全漏洞的安全策略。
鸣谢
许可证
MIT许可证(MIT)。请参阅许可证文件以获取更多信息。