[增添]添加了datasource的setting数据库以及默认值

This commit is contained in:
makotocc0107
2024-08-27 09:57:44 +08:00
parent d111dfaea4
commit 72eb990970
10955 changed files with 978898 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
---
title: Getting started
---
import LaracastsBanner from "@components/LaracastsBanner.astro"
<LaracastsBanner
title="Setting up a Plugin"
description="Watch the Build Advanced Components for Filament series on Laracasts - it will teach you how to get started with your plugin. The text-based guide on this page can also give a good overview."
url="https://laracasts.com/series/build-advanced-components-for-filament/episodes/12"
series="building-advanced-components"
/>
## Overview
While Filament comes with virtually any tool you'll need to build great apps, sometimes you'll need to add your own functionality either for just your app or as redistributable packages that other developers can include in their own apps. This is why Filament offers a plugin system that allows you to extend its functionality.
Before we dive in, it's important to understand the different contexts in which plugins can be used. There are two main contexts:
1. **Panel Plugins**: These are plugins that are used with [Panel Builders](/docs/3.x/panels/installation). They are typically used only to add functionality when used inside a Panel or as a complete Panel in and of itself. Examples of this are:
1. A plugin that adds specific functionality to the dashboard in the form of Widgets.
2. A plugin that adds a set of Resources / functionality to an app like a Blog or User Management feature.
2. **Standalone Plugins**: These are plugins that are used in any context outside a Panel Builder. Examples of this are:
1. A plugin that adds custom fields to be used with the [Form Builders](/docs/3.x/forms/installation/).
2. A plugin that adds custom columns or filters to the [Table Builders](/docs/3.x/tables/installation/).
Although these are two different mental contexts to keep in mind when building plugins, they can be used together inside the same plugin. They do not have to be mutually exclusive.
## Important Concepts
Before we dive into the specifics of building plugins, there are a few concepts that are important to understand. You should familiarize yourself with the following before building a plugin:
1. [Laravel Package Development](https://laravel.com/docs/packages)
2. [Spatie Package Tools](https://github.com/spatie/laravel-package-tools)
3. [Filament Asset Management](/docs/3.x/support/assets)
### The Plugin object
Filament v3 introduces the concept of a Plugin object that is used to configure the plugin. This object is a simple PHP class that implements the `Filament\Contracts\Plugin` interface. This class is used to configure the plugin and is the main entry point for the plugin. It is also used to register Resources and Icons that might be used by your plugin.
While the plugin object is extremely helpful, it is not required to build a plugin. You can still build plugins without using the plugin object as you can see in the [Building a Panel Plugin](/docs/3.x/support/plugins/build-a-panel-plugin) tutorial.
> **Info**
> The Plugin object is only used for Panel Providers. Standalone Plugins do not use this object. All configuration for Standalone Plugins should be handled in the plugin's service provider.
### Registering Assets
All [asset registration](/docs/3.x/support/assets), including CSS, JS and Alpine Components, should be done through the plugin's service provider in the `packageBooted()` method. This allows Filament to register the assets with the Asset Manager and load them when needed.
## Creating a Plugin
While you can certainly build plugins from scratch, we recommend using the [Filament Plugin Skeleton](https://github.com/filamentphp/plugin-skeleton) to quickly get started. This skeleton includes all the necessary boilerplate to get you up and running quickly.
### Usage
To use the skeleton, simply go to the GitHub repo and click the "Use this template" button. This will create a new repo in your account with the skeleton code. After that, you can clone the repo to your machine. Once you have the code on your machine, navigate to the root of the project and run the following command:
```bash
php ./configure.php
```
This will ask you a series of questions to configure the plugin. Once you've answered all the questions, the script will stub out a new plugin for you, and you can begin to build your amazing new extension for Filament.
## Upgrading existing plugins
Since every plugin varies greatly in its scope of use and functionality, there is no one size fits all approaches to upgrading existing plugins. However, one thing to note, that is consistent to all plugins is the deprecation of the `PluginServiceProvider`.
In your plugin service provider, you will need to change it to extend the PackageServiceProvider instead. You will also need to add a static `$name` property to the service provider. This property is used to register the plugin with Filament. Here is an example of what your service provider might look like:
```php
class MyPluginServiceProvider extends PackageServiceProvider
{
public static string $name = 'my-plugin';
public function configurePackage(Package $package): void
{
$package->name(static::$name);
}
}
```
### Helpful links
Please read this guide in its entirety before upgrading your plugin. It will help you understand the concepts and how to build your plugin.
1. [Filament Asset Management](/docs/3.x/support/assets)
2. [Panel Plugin Development](/docs/3.x/panels/plugins)
3. [Icon Management](/docs/3.x/support/icons)
4. [Colors Management](/docs/3.x/support/colors)
5. [Style Customization](/docs/3.x/support/style-customization)

View File

@@ -0,0 +1,212 @@
---
title: Build a panel plugin
---
import LaracastsBanner from "@components/LaracastsBanner.astro"
<LaracastsBanner
title="Panel Builder Plugins"
description="Watch the Build Advanced Components for Filament series on Laracasts - it will teach you how to get started with your plugin. The text-based guide on this page can also give a good overview."
url="https://laracasts.com/series/build-advanced-components-for-filament/episodes/16"
series="building-advanced-components"
/>
## Preface
Please read the docs on [panel plugin development](/docs/3.x/panels/plugins) and the [getting started guide](/docs/3.x/support/plugins/getting-started) before continuing.
## Overview
In this walkthrough, we'll build a simple plugin that adds a new form field that can be used in forms. This also means it will be available to users in their panels.
You can find the final code for this plugin at [https://github.com/awcodes/clock-widget](https://github.com/awcodes/clock-widget).
## Step 1: Create the plugin
First, we'll create the plugin using the steps outlined in the [getting started guide](/docs/3.x/support/plugins/getting-started#creating-a-plugin).
## Step 2: Clean up
Next, we'll clean up the plugin to remove the boilerplate code we don't need. This will seem like a lot, but since this is a simple plugin, we can remove a lot of the boilerplate code.
Remove the following directories and files:
1. `config`
1. `database`
1. `src/Commands`
1. `src/Facades`
1. `stubs`
Since our plugin doesn't have any settings or additional methods needed for functionality, we can also remove the `ClockWidgetPlugin.php` file.
1. `ClockWidgetPlugin.php`
Since Filament v3 recommends that users style their plugins with a custom filament theme, we'll remove the files needed for using css in the plugin. This is optional, and you can still use css if you want, but it is not recommended.
1. `resources/css`
1. `postcss.config.js`
1. `tailwind.config.js`
Now we can clean up our `composer.json` file to remove unneeded options.
```json
"autoload": {
"psr-4": {
// We can remove the database factories
"Awcodes\\ClockWidget\\Database\\Factories\\": "database/factories/"
}
},
"extra": {
"laravel": {
// We can remove the facade
"aliases": {
"ClockWidget": "Awcodes\\ClockWidget\\Facades\\ClockWidget"
}
}
},
```
The last step is to update the `package.json` file to remove unneeded options. Replace the contents of `package.json` with the following.
```json
{
"private": true,
"type": "module",
"scripts": {
"dev": "node bin/build.js --dev",
"build": "node bin/build.js"
},
"devDependencies": {
"esbuild": "^0.17.19"
}
}
```
Then we need to install our dependencies.
```bash
npm install
```
You may also remove the Testing directories and files, but we'll leave them in for now, although we won't be using them for this example, and we highly recommend that you write tests for your plugins.
## Step 3: Setting up the provider
Now that we have our plugin cleaned up, we can start adding our code. The boilerplate in the `src/ClockWidgetServiceProvider.php` file has a lot going on so, let's delete everything and start from scratch.
> In this example, we will be registering an [async Alpine component](../assets#asynchronous-alpinejs-components). Since these assets are only loaded on request, we can register them as normal in the `packageBooted()` method. If you are registering assets, like CSS or JS files, that get loaded on every page regardless of if they are used or not, you should register them in the `register()` method of the `Plugin` configuration object, using [`$panel->assets()`](../../panels/configuration#registering-assets-for-a-panel). Otherwise, if you register them in the `packageBooted()` method, they will be loaded in every panel, regardless of whether or not the plugin has been registered for that panel.
We need to be able to register our Widget with the panel and load our Alpine component when the widget is used. To do this, we'll need to add the following to the `packageBooted` method in our service provider. This will register our widget component with Livewire and our Alpine component with the Filament Asset Manager.
```php
use Filament\Support\Assets\AlpineComponent;
use Filament\Support\Facades\FilamentAsset;
use Livewire\Livewire;
use Spatie\LaravelPackageTools\Package;
use Spatie\LaravelPackageTools\PackageServiceProvider;
class ClockWidgetServiceProvider extends PackageServiceProvider
{
public static string $name = 'clock-widget';
public function configurePackage(Package $package): void
{
$package->name(static::$name)
->hasViews()
->hasTranslations();
}
public function packageBooted(): void
{
Livewire::component('clock-widget', ClockWidget::class);
// Asset Registration
FilamentAsset::register(
assets:[
AlpineComponent::make('clock-widget', __DIR__ . '/../resources/dist/clock-widget.js'),
],
package: 'awcodes/clock-widget'
);
}
}
```
## Step 4: Create the widget
Now we can create our widget. We'll first need to extend Filament's `Widget` class in our `ClockWidget.php` file and tell it where to find the view for the widget. Since we are using the PackageServiceProvider to register our views, we can use the `::` syntax to tell Filament where to find the view.
```php
use Filament\Widgets\Widget;
class ClockWidget extends Widget
{
protected static string $view = 'clock-widget::widget';
}
```
Next, we'll need to create the view for our widget. Create a new file at `resources/views/widget.blade.php` and add the following code. We'll make use of Filament's blade components to save time on writing the html for the widget.
We are using async Alpine to load our Alpine component, so we'll need to add the `x-ignore` attribute to the div that will load our component. We'll also need to add the `ax-load` attribute to the div to tell Alpine to load our component. You can learn more about this in the [Core Concepts](/docs/3.x/support/assets#asynchronous-alpinejs-components) section of the docs.
```blade
<x-filament-widgets::widget>
<x-filament::section>
<x-slot name="heading">
{{ __('clock-widget::clock-widget.title') }}
</x-slot>
<div
x-ignore
ax-load
ax-load-src="{{ \Filament\Support\Facades\FilamentAsset::getAlpineComponentSrc('clock-widget', 'awcodes/clock-widget') }}"
x-data="clockWidget()"
class="text-center"
>
<p>{{ __('clock-widget::clock-widget.description') }}</p>
<p class="text-xl" x-text="time"></p>
</div>
</x-filament::section>
</x-filament-widgets::widget>
```
Next, we need to write our Alpine component in `src/js/index.js`. And build our assets with `npm run build`.
```js
export default function clockWidget() {
return {
time: new Date().toLocaleTimeString(),
init() {
setInterval(() => {
this.time = new Date().toLocaleTimeString();
}, 1000);
}
}
}
```
We should also add translations for the text in the widget so users can translate the widget into their language. We'll add the translations to `resources/lang/en/widget.php`.
```php
return [
'title' => 'Clock Widget',
'description' => 'Your current time is:',
];
```
## Step 5: Update your README
You'll want to update your `README.md` file to include instructions on how to install your plugin and any other information you want to share with users, Like how to use it in their projects. For example:
```php
// Register the plugin and/or Widget in your Panel provider:
use Awcodes\ClockWidget\ClockWidgetWidget;
public function panel(Panel $panel): Panel
{
return $panel
->widgets([
ClockWidgetWidget::class,
]);
}
```
And, that's it, our users can now install our plugin and use it in their projects.

View File

@@ -0,0 +1,280 @@
---
title: Build a standalone plugin
---
## Preface
Please read the docs on [panel plugin development](/docs/3.x/panels/plugins/) and the [getting started guide](/docs/3.x/support/plugins/getting-started) before continuing.
## Overview
In this walkthrough, we'll build a simple plugin that adds a new form component that can be used in forms. This also means it will be available to users in their panels.
You can find the final code for this plugin at [https://github.com/awcodes/headings](https://github.com/awcodes/headings).
## Step 1: Create the plugin
First, we'll create the plugin using the steps outlined in the [getting started guide](/docs/3.x/support/plugins/getting-started#creating-a-plugin).
## Step 2: Clean up
Next, we'll clean up the plugin to remove the boilerplate code we don't need. This will seem like a lot, but since this is a simple plugin, we can remove a lot of the boilerplate code.
Remove the following directories and files:
1. `bin`
1. `config`
1. `database`
1. `src/Commands`
1. `src/Facades`
1. `stubs`
1. `tailwind.config.js`
Now we can clean up our `composer.json` file to remove unneeded options.
```json
"autoload": {
"psr-4": {
// We can remove the database factories
"Awcodes\\Headings\\Database\\Factories\\": "database/factories/"
}
},
"extra": {
"laravel": {
// We can remove the facade
"aliases": {
"Headings": "Awcodes\\Headings\\Facades\\ClockWidget"
}
}
},
```
Normally, Filament v3 recommends that users style their plugins with a custom filament theme, but for the sake of example let's provide our own stylesheet that can be loaded asynchronously using the new `x-load` features in Filament v3. So, let's update our `package.json` file to include cssnano, postcss, postcss-cli and postcss-nesting to build our stylesheet.
```json
{
"private": true,
"scripts": {
"build": "postcss resources/css/index.css -o resources/dist/headings.css"
},
"devDependencies": {
"cssnano": "^6.0.1",
"postcss": "^8.4.27",
"postcss-cli": "^10.1.0",
"postcss-nesting": "^12.0.0"
}
}
```
Then we need to install our dependencies.
```bash
npm install
```
We will also need to update our `postcss.config.js` file to configure postcss.
```js
module.exports = {
plugins: [
require('postcss-nesting')(),
require('cssnano')({
preset: 'default',
}),
],
};
```
You may also remove the testing directories and files, but we'll leave them in for now, although we won't be using them for this example, and we highly recommend that you write tests for your plugins.
## Step 3: Setting up the provider
Now that we have our plugin cleaned up, we can start adding our code. The boilerplate in the `src/HeadingsServiceProvider.php` file has a lot going on so, let's delete everything and start from scratch.
We need to be able to register our stylesheet with the Filament Asset Manager so that we can load it on demand in our blade view. To do this, we'll need to add the following to the `packageBooted` method in our service provider.
***Note the `loadedOnRequest()` method. This is important, because it tells Filament to only load the stylesheet when it's needed.***
```php
namespace Awcodes\Headings;
use Filament\Support\Assets\Css;
use Filament\Support\Facades\FilamentAsset;
use Spatie\LaravelPackageTools\Package;
use Spatie\LaravelPackageTools\PackageServiceProvider;
class HeadingsServiceProvider extends PackageServiceProvider
{
public static string $name = 'headings';
public function configurePackage(Package $package): void
{
$package->name(static::$name)
->hasViews();
}
public function packageBooted(): void
{
FilamentAsset::register([
Css::make('headings', __DIR__ . '/../resources/dist/headings.css')->loadedOnRequest(),
], 'awcodes/headings');
}
}
```
## Step 4: Creating our component
Next, we'll need to create our component. Create a new file at `src/Heading.php` and add the following code.
```php
namespace Awcodes\Headings;
use Closure;
use Filament\Forms\Components\Component;
use Filament\Support\Colors\Color;
use Filament\Support\Concerns\HasColor;
class Heading extends Component
{
use HasColor;
protected string | int $level = 2;
protected string | Closure $content = '';
protected string $view = 'headings::heading';
final public function __construct(string | int $level)
{
$this->level($level);
}
public static function make(string | int $level): static
{
return app(static::class, ['level' => $level]);
}
protected function setUp(): void
{
parent::setUp();
$this->dehydrated(false);
}
public function content(string | Closure $content): static
{
$this->content = $content;
return $this;
}
public function level(string | int $level): static
{
$this->level = $level;
return $this;
}
public function getColor(): array
{
return $this->evaluate($this->color) ?? Color::Amber;
}
public function getContent(): string
{
return $this->evaluate($this->content);
}
public function getLevel(): string
{
return is_int($this->level) ? 'h' . $this->level : $this->level;
}
}
```
## Step 5: Rendering our component
Next, we'll need to create the view for our component. Create a new file at `resources/views/heading.blade.php` and add the following code.
We are using x-load to asynchronously load stylesheet, so it's only loaded when necessary. You can learn more about this in the [Core Concepts](/docs/3.x/support/assets#lazy-loading-css) section of the docs.
```blade
@php
$level = $getLevel();
$color = $getColor();
@endphp
<{{ $level }}
x-data
x-load-css="[@js(\Filament\Support\Facades\FilamentAsset::getStyleHref('headings', package: 'awcodes/headings'))]"
{{
$attributes
->class([
'headings-component',
match ($color) {
'gray' => 'text-gray-600 dark:text-gray-400',
default => 'text-custom-500',
},
])
->style([
\Filament\Support\get_color_css_variables($color, [500]) => $color !== 'gray',
])
}}
>
{{ $getContent() }}
</{{ $level }}>
```
## Step 6: Adding some styles
Next, let's provide some custom styling for our field. We'll add the following to `resources/css/index.css`. And run `npm run build` to compile our css.
```css
.headings-component {
&:is(h1, h2, h3, h4, h5, h6) {
font-weight: 700;
letter-spacing: -.025em;
line-height: 1.1;
}
&h1 {
font-size: 2rem;
}
&h2 {
font-size: 1.75rem;
}
&h3 {
font-size: 1.5rem;
}
&h4 {
font-size: 1.25rem;
}
&h5,
&h6 {
font-size: 1rem;
}
}
```
Then we need to build our stylesheet.
```bash
npm run build
```
## Step 7: Update your README
You'll want to update your `README.md` file to include instructions on how to install your plugin and any other information you want to share with users, Like how to use it in their projects. For example:
```php
use Awcodes\Headings\Heading;
Heading::make(2)
->content('Product Information')
->color(Color::Lime),
```
And, that's it, our users can now install our plugin and use it in their projects.