Overview
The service provider is the entry point for your plugin. It handles registration of migrations, settings, dependencies, and installation/uninstallation commands.
BlogServiceProvider Example
<?php
namespace Webkul\Blog;
use Filament\Panel;
use Filament\Support\Assets\Css;
use Filament\Support\Facades\FilamentAsset;
use Webkul\PluginManager\Console\Commands\InstallCommand;
use Webkul\PluginManager\Console\Commands\UninstallCommand;
use Webkul\PluginManager\Package;
use Webkul\PluginManager\PackageServiceProvider;
class BlogServiceProvider extends PackageServiceProvider
{
public static string $name = 'blogs';
public static string $viewNamespace = 'blogs';
public function configureCustomPackage(Package $package): void
{
$package->name(static::$name)
->hasViews()
->hasTranslations()
->hasMigrations([
// Migration files will be listed here
])
->runsMigrations()
->hasSettings([
// Settings migrations will be listed here
])
->runsSettings()
->hasDependencies([
'website',
])
->hasInstallCommand(function (InstallCommand $command) {
$command
->installDependencies()
->runsMigrations();
})
->hasUninstallCommand(function (UninstallCommand $command) {})
->icon('blog');
}
public function packageBooted(): void
{
FilamentAsset::register([
Css::make('blogs', __DIR__.'/../resources/dist/blogs.css'),
], 'blogs');
}
public function packageRegistered(): void
{
Panel::configureUsing(function (Panel $panel): void {
$panel->plugin(BlogPlugin::make());
});
}
}The base PackageServiceProvider class lives in the plugin-manager plugin (Webkul\PluginManager\PackageServiceProvider) and extends Spatie's laravel-package-tools service provider. The Package instance passed to configureCustomPackage() is Webkul\PluginManager\Package, which adds plugin-specific capabilities (settings, seeders, dependencies, install/uninstall commands, icon) on top of the Spatie package class.
Service Provider Configuration
Registering Migrations
Migrations are crucial for setting up your plugin's database schema. Register them in the service provider:
public function configureCustomPackage(Package $package): void
{
$package->name(static::$name)
->hasViews()
->hasTranslations()
->hasMigrations([
'2025_03_06_093011_create_blogs_categories_table',
'2025_03_06_094011_create_blogs_posts_table',
'2025_03_07_065635_create_blogs_tags_table',
'2025_03_07_065715_create_blogs_post_tags_table',
'2025_09_03_070414_alter_blogs_posts_table',
])
->runsMigrations();
}The hasMigrations() method registers the migrations that will be used by the application, while runsMigrations() ensures they are executed during plugin installation.
Registering Settings
Settings allow users to configure your plugin. Register them like this:
public function configureCustomPackage(Package $package): void
{
$package->name(static::$name)
->hasViews()
->hasTranslations()
->hasMigrations([...])
->runsMigrations()
->hasSettings([
'2025_01_17_094021_create_inventories_operation_settings'
])
->runsSettings();
}The hasSettings() method registers setting migrations from the plugin's database/settings directory, while runsSettings() ensures they are executed during plugin installation. The blogs plugin has no settings migrations; the example above uses one from the inventories plugin.
Registering Seeders
Seeders populate the database with initial data. Register your seeder class with hasSeeder() (or several with hasSeeders()), and call runsSeeders() on the install command so it runs during installation. The maintenance plugin uses this approach:
use Webkul\Maintenance\Database\Seeders\DatabaseSeeder;
->hasSeeder(DatabaseSeeder::class)
->hasInstallCommand(function (InstallCommand $command) {
$command
->runsMigrations()
->runsSeeders();
})The plugin's Database\Seeders\DatabaseSeeder class then calls the individual seeders.
Registering Routes
If your plugin exposes web or API routes, place the files in the plugin's routes/ directory and register them with hasRoute() or hasRoutes():
->hasRoutes(['web', 'api'])Route files are only loaded when the plugin is installed (or marked as core), so an uninstalled plugin never exposes its endpoints.
Managing Dependencies
If your plugin depends on other plugins, declare them using the hasDependencies() method:
->hasDependencies([
'website',
])This ensures that when your plugin is installed, its dependencies are installed first. In this example, the 'website' plugin will be installed before the 'blogs' plugin.
Installation and Uninstallation
The hasInstallCommand() and hasUninstallCommand() methods define what happens when your plugin is installed or uninstalled:
->hasInstallCommand(function (InstallCommand $command) {
$command
->installDependencies()
->runsMigrations();
})
->hasUninstallCommand(function (UninstallCommand $command) {
// Cleanup operations
});When uninstalling a plugin, the system will prompt for confirmation (pass the --force option to skip it):
Are you sure you want to uninstall this package? This action cannot be undone! (yes/no) [no]:
> yesIf you attempt to uninstall a plugin that other installed plugins depend on, the uninstallation is blocked with a warning:
Package website has installed dependents: blogs. Please uninstall these dependents first!You can also hook into both commands with startWith() and endWith() callbacks to run custom logic before or after the installation or uninstallation.
After every install or uninstall the plugin manager refreshes the application caches (via optimize:clear, followed by a background optimize in production), so the panel navigation immediately reflects the plugin change.
Plugin Registration
The packageRegistered() method is used to register your plugin with the application panels after the package is loaded. Combined with the Package::isPluginInstalled() check inside the plugin's register() method, it ensures the plugin's UI is loaded only when it is installed, keeping the system modular and safe.
public function packageRegistered(): void
{
Panel::configureUsing(function (Panel $panel): void {
$panel->plugin(BlogPlugin::make());
});
}Why this method is important
- Registers the Filament plugin with the panel
- Prevents loading UI features when the plugin is not installed
- Avoids errors caused by missing migrations or settings
- Keeps plugin loading clean and dependency-aware
When to use it
Use packageRegistered() to:
- Attach Filament plugins
- Configure panels conditionally
- Control when your plugin becomes visible in the admin UI
In short, packageRegistered() is the safe and correct place to register your plugin, ensuring it loads only when the plugin is properly installed and ready to use.
Additional Configuration
The packageBooted() method allows you to add additional configurations, such as registering CSS, JavaScript, or other resources:
public function packageBooted(): void
{
FilamentAsset::register([
Css::make('blogs', __DIR__.'/../resources/dist/blogs.css'),
], 'blogs');
}Registering Your plugin's Provider
After creating your service provider, register it in bootstrap/providers.php:
<?php
return [
// Other service providers
Webkul\Blog\BlogServiceProvider::class,
];