Languages

Version

Theme

高级

文件生成

介绍

Filament 引入了许多生成文件的 CLI 命令。本文将接受如何自定义生成文件。

Filament 生成的大部分文件都是 PHP 类。Filament 使用 nette/php-generator 以编程方式生成类,而不是使用模板文件。这样做的优点是,生成的文件时有更多的灵活性,当你需要支持与 Filament 一样多的不同配置选项时,这一点非常重要。

每个类型的类都由 ClassGenerator 类生成。以下是 Filament 使用的 ClassGenerator 类列表:

  • Filament\Actions\Commands\FileGenerators\ExporterClassGeneratormake:filament-exporter 命令使用的类。
  • Filament\Actions\Commands\FileGenerators\ImporterClassGeneratormake:filament-importer 命令使用的类。
  • Filament\Forms\Commands\FileGenerators\FieldClassGeneratormake:filament-form-field 命令使用的类。
  • Filament\Forms\Commands\FileGenerators\FormSchemaClassGeneratormake:filament-form 命令使用的类。
  • Filament\Forms\Commands\FileGenerators\LivewireFormComponentClassGeneratormake:filament-livewire-form 命令使用的类。
  • Filament\Infolists\Commands\FileGenerators\EntryClassGeneratormake:filament-infolist-entry 命令使用的类。
  • Filament\Commands\FileGenerators\Resources\Pages\ResourceCreateRecordPageClassGeneratormake:filament-resourcemake:filament-page 命令使用的类。
  • Filament\Commands\FileGenerators\Resources\Pages\ResourceCustomPageClassGeneratormake:filament-resourcemake:filament-page 命令使用的类。
  • Filament\Commands\FileGenerators\Resources\Pages\ResourceEditRecordPageClassGeneratormake:filament-resourcemake:filament-page 命令使用的类。
  • Filament\Commands\FileGenerators\Resources\Pages\ResourceListRecordsPageClassGeneratormake:filament-resourcemake:filament-page 命令使用的类。
  • Filament\Commands\FileGenerators\Resources\Pages\ResourceManageRecordsPageClassGeneratormake:filament-resourcemake:filament-page 命令使用的类。
  • Filament\Commands\FileGenerators\Resources\Pages\ResourceManageRelatedRecordsPageClassGeneratormake:filament-resourcemake:filament-page 命令使用的类。
  • Filament\Commands\FileGenerators\Resources\Pages\ResourceViewRecordPageClassGeneratormake:filament-resourcemake:filament-page 命令使用的类。
  • Filament\Commands\FileGenerators\Resources\SchemasResourceFormSchemaClassGeneratormake:filament-resource 命令使用的类。
  • Filament\Commands\FileGenerators\Resources\SchemasResourceInfolistSchemaClassGeneratormake:filament-resource 命令使用的类。
  • Filament\Commands\FileGenerators\Resources\SchemasResourceTableClassGeneratormake:filament-resource 命令使用的类。
  • Filament\Commands\FileGenerators\Resources\RelationManagerClassGeneratormake:filament-relation-manager 命令使用的类。
  • Filament\Commands\FileGenerators\Resources\ResourceClassGeneratormake:filament-resource 命令使用的类。
  • Filament\Commands\FileGenerators\ClusterClassGeneratormake:filament-cluster 命令使用的类。
  • Filament\Commands\FileGenerators\CustomPageClassGeneratormake:filament-page 命令使用的类。
  • Filament\Commands\FileGenerators\PanelProviderClassGeneratorfilament:installmake:filament-panel commands.
  • Filament\Schemas\Commands\FileGenerators\ComponentClassGeneratormake:filament-schema-component 命令使用的类。
  • Filament\Schemas\Commands\FileGenerators\LivewireSchemaComponentClassGeneratormake:filament-livewire-schema 命令使用的类。
  • Filament\Schemas\Commands\FileGenerators\SchemaClassGeneratormake:filament-schema 命令使用的类。
  • Filament\Tables\Commands\FileGenerators\ColumnClassGeneratormake:filament-table-column 命令使用的类。
  • Filament\Tables\Commands\FileGenerators\LivewireTableComponentClassGeneratormake:filament-livewire-table 命令使用的类。
  • Filament\Tables\Commands\FileGenerators\TableClassGeneratormake:filament-table 命令使用的类。
  • Filament\Widgets\Commands\FileGenerators\ChartWidgetClassGeneratormake:filament-widget 命令使用的类。
  • Filament\Widgets\Commands\FileGenerators\CustomWidgetClassGeneratormake:filament-widget 命令使用的类。
  • Filament\Widgets\Commands\FileGenerators\StatsOverviewWidgetClassGeneratormake:filament-widget 命令使用的类。
  • Filament\Widgets\Commands\FileGenerators\TableWidgetClassGeneratormake:filament-widget 命令使用的类。

类生成器剖析

了解类生成器的最好方式是阅读其源码。它们都遵循非常相似的模板,并且使用了 nette/php-generator 的特性。

此处是一些需要留意的方法:

  • __construct() 接收要传入生成器的参数。这是你可以访问的作为生成类的上下文的所有信息。
  • getImports() returns the imports that are used in the class being generated. This is not an exclusive list, and imports can be added while generating properties and methods as well, if that is easier than providing them in advance.
  • getExtends() returns the fully qualified name of the class being extended.
  • addTraitsToClass() is used to add traits to the class being generated. The Class object from nette/php-generator is passed in as a parameter.
  • addPropertiesToClass() is used to add properties to the class being generated. The Class object from nette/php-generator is passed in as a parameter.
  • add*PropertyToClass() methods are used to add a single property to the class being generated. The Class object from nette/php-generator is passed in as a parameter. They are usually called from addPropertiesToClass().
  • addMethodsToClass() is used to add methods to the class being generated. The Class object from nette/php-generator is passed in as a parameter.
  • add*MethodToClass() methods are used to add a single method to the class being generated. The Class object from nette/php-generator is passed in as a parameter. They are usually called from addMethodsToClass().

替换类生成器

要启用修改文件生成方式的能力,你需要识别正确的类生成器(详见上述列表)。

要对其进行替换,请创建一个新类,使之继承你想替换的类生成器。比如,如果你想替换 ResourceClassGenerator,请生成新类如下:

namespace App\Filament\Commands\FileGenerators\Resources;

use Filament\Commands\FileGenerators\Resources\ResourceClassGenerator as BaseResourceClassGenerator;

class ResourceClassGenerator extends BaseResourceClassGenerator
{
   // ...
}

你同时需要在服务容器中注册绑定它。你可以在服务提供者(如 AppServiceProvider)中实现注册绑定:

use App\Filament\Commands\FileGenerators\Resources\ResourceClassGenerator;
use Filament\Commands\FileGenerators\Resources\ResourceClassGenerator as BaseResourceClassGenerator;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        // ...
    
        $this->app->bind(BaseResourceClassGenerator::class, ResourceClassGenerator::class);
        
        // ...
    }
}

在类中自定义已有属性和方法

查看类生成器的源码时,请定位到你想要自定义的属性或者方法。你可用使用相同的名称在类生成器中定义新方法来进行重写。比如,下例是一个你可以查看的方法,它将 $navigationIcon 属性添加资源类:

use BackedEnum;
use Filament\Support\Icons\Heroicon;
use Nette\PhpGenerator\ClassType;
use Nette\PhpGenerator\Literal;

protected function addNavigationIconPropertyToClass(ClassType $class): void
{
    $this->namespace->addUse(BackedEnum::class);
    $this->namespace->addUse(Heroicon::class);

    $property = $class->addProperty('navigationIcon', new Literal('Heroicon::OutlinedRectangleStack'))
        ->setProtected()
        ->setStatic()
        ->setType('string|BackedEnum|null');
    $this->configureNavigationIconProperty($property);
}

你可以重写该方法以改变其行为,或者仅仅重写 configureNavigationIconProperty() 方法,以勾入到属性的配置。比如,将属性的 protected 改为 public

use Nette\PhpGenerator\Property;

protected function configureNavigationIconProperty(Property $property): void
{
    $property->setPublic();
}

向类中添加新属性或方法

要添加新属性或方法到类中,你可以在 addPropertiesToClass()addMethodsToClass() 中实现。要继承已有的属性,而不是替换,请确保调用在方法的起始位置调用 parent::addPropertiesToClass() 或者 parent::addMethodsToClass()。比如,下例展示了如何添加新属性到资源类中:

use Nette\PhpGenerator\ClassType;
use Nette\PhpGenerator\Literal;

protected function addPropertiesToClass(ClassType $class): void
{
    parent::addPropertiesToClass($class);

    $class->addProperty('navigationSort', 10)
        ->setProtected()
        ->setStatic()
        ->setType('?int');
}
Edit on GitHub

Still need help? Join our Discord community or open a GitHub discussion

Previous
Enum 技巧