guava/filament-nested-resources

1.2.0 2024-06-27 06:50 UTC

README

Filament Cluster Banner

Filament Nested Resources

Latest Version on Packagist Total Downloads

Filament Nested Resources 允许您创建任何深度的嵌套资源。这对于过于复杂而无法使用关系管理器,但又不能作为独立资源的资源非常有用。

首次公开发布在这里。

展示

Screenshot 1 Screenshot 2

支持我们

您的支持对我们插件持续进步至关重要。我们感谢每一位至今为止为我们旅程做出贡献的用户。

虽然我们的插件对所有用户都开放,但如果您将其用于商业目的,并认为它为您的事业增添了显著价值,我们恳请您考虑通过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)

快速入门

为了设置嵌套资源,您需要执行以下步骤

  1. 在您想要嵌套的资源(根和所有子资源)上,添加NestedResource特性。您将需要实现getAncestor方法。对于根资源,返回null,对于所有子资源,根据以下文档实现。
  2. 在第一步中资源的每一页上,添加NestedPage特性。
  3. 创建一个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特性添加到其中任何一个。

让我们假设展示截图中的场景,我们有以下模式

  1. Artist 模型。
  2. Album 模型(属于 Artist)。
  3. 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
        );
    }
}

ArtistResourceAlbumResource 的每一页上,我们添加 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)中的 indexcreate 页面。

自定义面包屑

每个资源都可以控制自己部分的面包屑,默认由一个 index 面包屑和一个 detail 面包屑组成。

index 面包屑通常重定向到索引页面。

detail 面包屑通常重定向到详情(编辑或查看)页面,默认情况下将显示记录的路线键(ID,如果没有进行其他配置)。

您可以通过 NestedResourcegetBreadcrumbRecordLabel 方法重写标签。

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)。请参阅 许可证文件 获取更多信息。