承接 timo-de-winter/filament-modifiable-plugins 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

timo-de-winter/filament-modifiable-plugins

Composer 安装命令:

composer require timo-de-winter/filament-modifiable-plugins

包简介

A helper package for when creating packages that provide filament resources.

README 文档

README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

A powerful package for creating highly customizable Filament plugins. This package empowers plugin developers to provide end-users with extensive customization options for resources, including navigation, forms, tables, clusters, and more.

Why Use This Package?

When building Filament plugins that provide resources or pages, you often want to give developers using your plugin the flexibility to customize various aspects such as:

  • Navigation properties (labels, icons, groups, sorting)
  • Page features (titles, slugs, schemas/forms)
  • Table components (columns, filters, actions)
  • Resource organization (clusters, parent items)
  • Tenant ownership relationships
  • And much more!

This package provides a clean, fluent API to make all of these customizations possible without requiring plugin users to override entire resource classes.

Requirements

  • PHP 8.3+
  • Laravel 11.x or 12.x
  • Filament 4.1+ or 5.0+

Installation

Install the package via Composer:

composer require timo-de-winter/filament-modifiable-plugins

No additional configuration or publishing is required. The package will auto-register via Laravel's package discovery.

Table of Contents

For Plugin Users

If you've installed a Filament plugin that uses this package, you can easily customize the plugin's resources without modifying the plugin's source code.

Basic Customization

Here's a comprehensive example showing all available customization options:

use Filament\Panel;
use YourVendor\YourPlugin\YourPlugin;
use YourVendor\YourPlugin\Resources\UserResource;
use App\Filament\Clusters\Settings;

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugins([
            YourPlugin::make()
                // Navigation customization
                ->navigationGroup('Settings', UserResource::class)
                ->label('System Users', UserResource::class)
                ->sort(10, UserResource::class)
                ->icon('heroicon-o-users', UserResource::class)
                ->activeIcon('heroicon-s-users', UserResource::class)
                ->badge('New', UserResource::class)
                ->badgeColor('success', UserResource::class)
                ->badgeTooltip('Recently added users', UserResource::class)

                // Cluster and organization
                ->cluster(Settings::class, UserResource::class)
                ->parentItem('user-management', UserResource::class)

                // Page customization
                ->title('Manage Users', UserResource::class)
                ->slug('system-users', UserResource::class)

                // Multi-tenancy
                ->tenantOwnershipRelationshipName('organization', UserResource::class)
        ]);
}

Navigation Customization

Control how resources appear in your Filament panel's navigation:

YourPlugin::make()
    ->navigationGroup('Settings', UserResource::class)
    ->label('Users', UserResource::class)
    ->sort(5, UserResource::class)
    ->icon('heroicon-o-users', UserResource::class)
    ->activeIcon('heroicon-s-users', UserResource::class)
    ->badge('12', UserResource::class)
    ->badgeColor('warning', UserResource::class)

All navigation methods support closures for dynamic values:

YourPlugin::make()
    ->badge(fn () => User::count(), UserResource::class)
    ->badgeColor(fn () => User::count() > 100 ? 'danger' : 'success', UserResource::class)

Page Customization

Customize page titles, slugs, and organization:

YourPlugin::make()
    ->title('User Management', UserResource::class)
    ->slug('manage-users', UserResource::class)
    ->cluster(Settings::class, UserResource::class)
    ->parentItem('system', UserResource::class)

Form/Schema Customization

Customize the form schema used in your resource's create and edit pages:

use Filament\Schemas\Schema;
use Filament\Schemas\Components\TextInput;
use Filament\Schemas\Components\Select;

YourPlugin::make()
    ->schema(function (Schema $schema) {
        return $schema
            ->components([
                TextInput::make('name')
                    ->required()
                    ->maxLength(255),
                TextInput::make('email')
                    ->email()
                    ->required(),
                Select::make('role')
                    ->options([
                        'admin' => 'Administrator',
                        'user' => 'User',
                    ])
                    ->required(),
            ]);
    }, UserResource::class)

Table Customization

Customize table columns, filters, and actions:

use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Actions\EditAction;
use Filament\Tables\Actions\DeleteAction;

YourPlugin::make()
    // Customize specific table elements
    ->columns([
        TextColumn::make('name')->searchable(),
        TextColumn::make('email')->searchable(),
        TextColumn::make('created_at')->dateTime(),
    ], UserResource::class)
    ->filters([
        SelectFilter::make('role')
            ->options([
                'admin' => 'Admin',
                'user' => 'User',
            ]),
    ], UserResource::class)
    ->recordActions([
        EditAction::make(),
        DeleteAction::make(),
    ], UserResource::class)
    ->toolbarActions([
        // Your toolbar/bulk actions here
    ], UserResource::class)

Alternatively, override the entire table configuration:

use Filament\Tables\Table;

YourPlugin::make()
    ->customTable(function (Table $table) {
        return $table
            ->columns([
                // Your columns
            ])
            ->filters([
                // Your filters
            ])
            ->recordActions([
                // Your actions
            ])
            ->toolbarActions([
                // Your toolbar actions
            ]);
    }, UserResource::class)

Targeting Specific Resources

When a plugin provides multiple resources, you can target specific ones by passing the resource class as the second parameter:

use YourVendor\YourPlugin\Resources\UserResource;
use YourVendor\YourPlugin\Resources\RoleResource;

YourPlugin::make()
    // Customize UserResource
    ->navigationGroup('User Management', UserResource::class)
    ->icon('heroicon-o-users', UserResource::class)

    // Customize RoleResource
    ->navigationGroup('User Management', RoleResource::class)
    ->icon('heroicon-o-shield-check', RoleResource::class)

    // This applies to all resources without specific customization
    ->sort(10)

Custom Relations and Pages

Override the relations and pages for a resource:

use YourVendor\YourPlugin\Resources\UserResource\RelationManagers\RolesRelationManager;
use YourVendor\YourPlugin\Resources\UserResource\Pages;

YourPlugin::make()
    ->customRelations([
        RolesRelationManager::class,
        // Your custom relation managers
    ], UserResource::class)
    ->customPages([
        'index' => Pages\ListUsers::class,
        'create' => Pages\CreateUser::class,
        'edit' => Pages\EditUser::class,
        // Your custom pages
    ], UserResource::class)

For Plugin Developers

If you're developing a Filament plugin and want to make your resources customizable, follow these steps.

Setting Up Your Plugin

1. Add the Trait to Your Plugin Class

Add the CanModifyResources trait to your plugin class:

<?php

namespace YourVendor\YourPlugin;

use Filament\Contracts\Plugin;
use Filament\Panel;
use TimoDeWinter\FilamentModifiablePlugins\Concerns\CanModifyResources;

class YourPlugin implements Plugin
{
    use CanModifyResources;

    public function getId(): string
    {
        return 'your-plugin-id';
    }

    public function register(Panel $panel): void
    {
        $panel->resources([
            Resources\UserResource::class,
            Resources\RoleResource::class,
        ]);
    }

    public function boot(Panel $panel): void
    {
        //
    }

    public static function make(): static
    {
        return app(static::class);
    }
}

Implementing Modifiable Resources

1. Add the Trait to Your Resource

Add the CanBeModified trait to each resource you want to make customizable:

<?php

namespace YourVendor\YourPlugin\Resources;

use Filament\Resources\Resource;
use TimoDeWinter\FilamentModifiablePlugins\Concerns\CanBeModified;

class UserResource extends Resource
{
    use CanBeModified;

    protected static ?string $model = User::class;

    protected static ?string $navigationIcon = 'heroicon-o-users';

    // Your resource implementation...
}

2. Implement Customizable Forms/Schemas

Use the getCustomSchema() method to allow form customization:

use Filament\Schemas\Schema;
use Filament\Schemas\Components\TextInput;

public static function schema(Schema $schema): Schema
{
    return self::getCustomSchema($schema, function (Schema $schema) {
        return $schema
            ->components([
                TextInput::make('name')
                    ->required()
                    ->maxLength(255),
                TextInput::make('email')
                    ->email()
                    ->required(),
                // Your default schema components...
            ]);
    });
}

3. Implement Customizable Tables

Use the getCustomTable() method with CustomizableTable for table customization:

use Filament\Tables\Table;
use TimoDeWinter\FilamentModifiablePlugins\CustomizableTable;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\TrashedFilter;
use Filament\Tables\Actions\EditAction;
use Filament\Tables\Actions\DeleteAction;

public static function table(Table $table): Table
{
    return self::getCustomTable($table, function (CustomizableTable $table) {
        return $table
            ->defaultColumns([
                TextColumn::make('id')->sortable(),
                TextColumn::make('name')->searchable()->sortable(),
                TextColumn::make('email')->searchable(),
                TextColumn::make('created_at')->dateTime(),
            ])
            ->defaultFilters([
                TrashedFilter::make(),
            ])
            ->defaultRecordActions([
                EditAction::make(),
                DeleteAction::make(),
            ])
            ->defaultToolbarActions([
                // Your default toolbar actions
            ]);
    });
}

4. Implement Customizable Relations

Use the getCustomRelations() method:

public static function getRelations(): array
{
    return self::getCustomRelations([
        RelationManagers\RolesRelationManager::class,
        // Your default relation managers...
    ]);
}

5. Implement Customizable Pages

Use the getCustomPages() method:

public static function getPages(): array
{
    return self::getCustomPages([
        'index' => Pages\ListUsers::class,
        'create' => Pages\CreateUser::class,
        'edit' => Pages\EditUser::class,
        // Your default pages...
    ]);
}

Best Practices

  1. Always provide sensible defaults - Your resources should work perfectly out of the box even if users don't customize them.

  2. Use the helper methods consistently - Always use getCustomSchema(), getCustomTable(), etc., in your resources to ensure customizations are applied.

  3. Document customization options - Let your users know which resources can be customized and provide examples in your plugin's documentation.

  4. Test with customizations - Include tests that verify customizations work correctly.

  5. Use type hints - The package fully supports IDE autocompletion and type checking.

Complete Resource Example

Here's a complete example of a properly implemented modifiable resource:

<?php

namespace YourVendor\YourPlugin\Resources;

use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Schemas\Components\TextInput;
use Filament\Tables\Table;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Actions\EditAction;
use Filament\Tables\Actions\DeleteAction;
use TimoDeWinter\FilamentModifiablePlugins\Concerns\CanBeModified;
use TimoDeWinter\FilamentModifiablePlugins\CustomizableTable;
use YourVendor\YourPlugin\Models\User;

class UserResource extends Resource
{
    use CanBeModified;

    protected static ?string $model = User::class;

    protected static ?string $navigationIcon = 'heroicon-o-users';

    protected static ?string $navigationGroup = 'Users';

    public static function schema(Schema $schema): Schema
    {
        return self::getCustomSchema($schema, function (Schema $schema) {
            return $schema
                ->components([
                    TextInput::make('name')
                        ->required()
                        ->maxLength(255),
                    TextInput::make('email')
                        ->email()
                        ->required()
                        ->unique(ignoreRecord: true),
                ]);
        });
    }

    public static function table(Table $table): Table
    {
        return self::getCustomTable($table, function (CustomizableTable $table) {
            return $table
                ->defaultColumns([
                    TextColumn::make('id')->sortable(),
                    TextColumn::make('name')->searchable()->sortable(),
                    TextColumn::make('email')->searchable(),
                    TextColumn::make('created_at')->dateTime()->sortable(),
                ])
                ->defaultFilters([
                    //
                ])
                ->defaultRecordActions([
                    EditAction::make(),
                    DeleteAction::make(),
                ])
                ->defaultToolbarActions([
                    //
                ]);
        });
    }

    public static function getRelations(): array
    {
        return self::getCustomRelations([
            //
        ]);
    }

    public static function getPages(): array
    {
        return self::getCustomPages([
            'index' => Pages\ListUsers::class,
            'create' => Pages\CreateUsers::class,
            'edit' => Pages\EditUsers::class,
        ]);
    }
}

Available Methods Reference

For Plugin Users (via Plugin Class)

Method Description
navigationGroup($group, $resource) Set the navigation group
label($label, $resource) Set the navigation label
sort($order, $resource) Set the navigation sort order
icon($icon, $resource) Set the navigation icon
activeIcon($icon, $resource) Set the active navigation icon
badge($badge, $resource) Set the navigation badge
badgeColor($color, $resource) Set the navigation badge color
badgeTooltip($tooltip, $resource) Set the navigation badge tooltip
parentItem($parent, $resource) Set the navigation parent item
cluster($cluster, $resource) Set the resource cluster
title($title, $resource) Set the page title
slug($slug, $resource) Set the resource slug
tenantOwnershipRelationshipName($name, $resource) Set tenant ownership relationship
schema($callback, $resource) Customize the form schema
columns($columns, $resource) Set table columns
filters($filters, $resource) Set table filters
recordActions($actions, $resource) Set table record actions
toolbarActions($actions, $resource) Set table toolbar actions
customTable($callback, $resource) Override entire table configuration
customRelations($relations, $resource) Set custom relation managers
customPages($pages, $resource) Set custom pages

All methods support closures for dynamic values and accept an optional resource class as the second parameter.

For Plugin Developers (via Resource Trait)

Method Description
getCustomSchema($schema, $default) Get customized schema or default
getCustomTable($table, $default) Get customized table or default
getCustomRelations($default) Get customized relations or default
getCustomPages($default) Get customized pages or default

Testing

Run the test suite:

composer test

Run tests with coverage:

composer test-coverage

Fix code style issues:

composer format

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

Security Vulnerabilities

If you discover a security vulnerability within this package, please send an e-mail to Timo de Winter via info@timodw.nl. All security vulnerabilities will be promptly addressed.

Please review our security policy on how to report security vulnerabilities.

Credits

License

The MIT License (MIT). Please see License File for more information.

Support

If you find this package helpful, please consider:

For issues, questions, or suggestions, please use the GitHub issue tracker.

timo-de-winter/filament-modifiable-plugins 适用场景与选型建议

timo-de-winter/filament-modifiable-plugins 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 3.01k 次下载、GitHub Stars 达 1, 最近一次更新时间为 2025 年 04 月 19 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「laravel」 「timo-de-winter」 「filament-modifiable-plugins」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 timo-de-winter/filament-modifiable-plugins 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 timo-de-winter/filament-modifiable-plugins 我们能提供哪些服务?
定制开发 / 二次开发

基于 timo-de-winter/filament-modifiable-plugins 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 3.01k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 7
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 1
  • Watchers: 2
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-04-19