Plugins¶
Plugins let you extend LacePHP without touching the core. Drop third-party or custom code into weave/Plugins, and LacePHP will auto-discover, register routes, middleware or CLI commands for you—keeping your application modular and upgrade-safe.
Why Plugins Matter¶
Modularity Keep reusable features in separate packages or folders, not mixed with your app or framework.
Discoverability LacePHP auto-discovers any class implementing PluginInterface under weave/Plugins.
Extensibility Plugins can register routes, middleware, service providers or CLI commands at boot time.
PluginManager Overview¶
LacePHP’s PluginManager handles discovery and registration:
use Lacebox\Sole\PluginManager;
$pm = new PluginManager();
$pm->discoverFromFolder(__DIR__); // load PHP files under weave/Plugins
$pm->discoverFromComposer('vendor'); // load composer packages with lace-plugin.json
$pm->registerAll($router, $config); // let plugins add routes/middleware
$pm->bootAll($config); // call plugin boot logic
$commands = $pm->getCommands(); // pull in CLI commands
Creating a Simple Plugin¶
Implement the PluginInterface in weave/Plugins/MyFeature/MyPlugin.php:
<?php namespace Weave\Plugins\MyFeature; use Lacebox\Shoelace\PluginInterface; use Lacebox\Shoelace\RouterInterface; class MyPlugin implements PluginInterface { public function register(RouterInterface $router, array $config): void { // e.g. add a new route $router->addRoute( 'GET', '/hello-plugin', fn() => 'Hello from MyPlugin!' ); } public function boot(array $config): void { // run once at framework startup if (! empty($config['myfeature']['enabled'])) { // set up services, load configs, etc. } } }
Enable any config in config/lace.php:
return [ 'myfeature' => [ 'enabled' => true, // other settings... ], ];
No further wiring is needed—LacePHP will discover and invoke your plugin automatically.
Built-in ShoeAI Plugin¶
LacePHP ships with an AI helper plugin under weave/Plugins/ShoeAI. It demonstrates:
Implementing both PluginInterface and CommandProviderInterface
Registering multiple CLI commands for AI features
Review weave/Plugins/ShoeAI/AiCommands.php:
<?php
namespace Weave\Plugins\ShoeAI;
use Lacebox\Shoelace\PluginInterface;
use Lacebox\Shoelace\CommandProviderInterface;
use Lacebox\Shoelace\RouterInterface;
use Lacebox\Sole\Cli;
use Weave\Plugins\ShoeAI\Agents\{
Credentials,
ShoeAIStatus,
ShoeGenie,
ShoeBuddy
};
class AiCommands implements PluginInterface, CommandProviderInterface
{
public function register(RouterInterface $router, array $config): void
{
// no HTTP routes needed here
}
public function boot(array $config): void
{
// optional boot-time setup
}
public function registerCommands(Cli $cli): void
{
$cli->register('ai:activate', 'Activate your AI license', fn($argv)=>Credentials::enable());
$cli->register('ai:status', 'Show AI subscription status', fn($argv)=>ShoeAIStatus::status());
$cli->register('ai:scaffold','Scaffold code from a prompt', fn($argv)=>ShoeGenie::scaffold($argv[2] ?? null));
$cli->register('ai:rollback','Rollback scaffolded code', fn($argv)=>ShoeGenie::rollback());
$cli->register('ai:buddy', 'AI peer-coding buddy', fn($argv)=>ShoeBuddy::ask($argv[2] ?? null, (int)($argv[3] ?? 0), $argv[4] ?? null));
}
}
When LacePHP starts, these commands become available:
php lace ai:activate
php lace ai:status
php lace ai:scaffold "Build a REST API for posts"
php lace ai:rollback
php lace ai:buddy Controllers/MyController.php 10 "Why does this line fail?"
Composer-Published Plugins¶
Publish a plugin as a Composer package:
Add a lace-plugin.json alongside your composer.json:
{ "pluginClass": "Vendor\\MyPlugin\\MainPlugin" }
Implement PluginInterface (and/or CommandProviderInterface) in MainPlugin.
Require via composer:
composer require vendor/my-laceplugin
LacePHP’s discoverFromComposer() will detect and load it automatically.
Registering CLI Commands Manually¶
Plugins (or your app) can add commands at runtime:
$pm->registerCommands([
\weave\Plugins\MyFeature\MyCommand::class,
]);
LacePHP will include these classes when assembling the CLI.
Best Practices¶
Single responsibility: per plugin group related features together.
Namespace correctly: follow PSR-4 under weave/Plugins/YourPlugin/.
Use Composer: for shareable plugins—others can install with composer require.
Keep `boot()` light: defer heavy work to services or on-demand hooks.
Warning
Plugin discovery loads every PHP file under weave/Plugins—avoid duplicate class names.
Ensure your register() logic does not override core routes or middleware unintentionally.
Sanitize configuration values before use in boot() to prevent runtime errors.
By writing plugins, even a complex AI feature like ShoeAI, you can add or share functionality cleanly, without touching LacePHP’s core code.