halilcosdu/laravel-command-banner
Installation:
composer require halilcosdu/laravel-command-banner
Publish the config file:
php artisan vendor:publish --provider="Halilcosdu\LaravelCommandBanner\CommandBannerServiceProvider" --tag="config"
Configure Allowed Environments:
Edit config/command-banner.php to define which environments can run which commands. Example:
'environments' => [
'local' => ['migrate', 'db:seed'],
'staging' => ['queue:work', 'cache:clear'],
'production' => ['queue:work', 'schedule:run'],
],
local can run migrate and db:seed.staging can run queue:work and cache:clear.production is restricted to critical commands like queue:work and schedule:run.First Use Case: Run a command in a restricted environment to test the banner:
APP_ENV=production php artisan migrate
If migrate isn’t in the production list, the command will fail with a clear error message:
Command "migrate" is not allowed in the "production" environment.
Define Restrictions:
Use the config file to map environments to allowed commands. Group commands by environment (e.g., local for development, production for read-only operations).
'environments' => [
'production' => ['queue:work', 'schedule:run', 'down'],
'staging' => ['migrate', 'db:seed', 'queue:work'],
],
Dynamic Environment Handling:
Override the APP_ENV dynamically in CI/CD pipelines or scripts:
APP_ENV=staging php artisan db:seed
The package respects the environment variable, so no additional logic is needed.
Command-Level Granularity:
Restrict sensitive commands (e.g., migrate, down) to specific environments while allowing broader access for others (e.g., queue:work in all environments):
'environments' => [
'*' => ['queue:work'], // All environments
'local' => ['migrate', 'db:seed'],
],
Integration with Artisan Events:
Extend functionality by listening to CommandStarting events in your own service providers:
use Halilcosdu\LaravelCommandBanner\Events\CommandBlocked;
Event::listen(CommandBlocked::class, function ($event) {
Log::warning("Blocked command: {$event->command} in {$event->environment}");
});
Custom Error Messages: Override the default banner message by publishing the language file:
php artisan vendor:publish --provider="Halilcosdu\LaravelCommandBanner\CommandBannerServiceProvider" --tag="lang"
Edit resources/lang/en/command-banner.php:
'blocked' => '⚠️ Command :command is restricted in :environment. Allowed commands: :allowed_commands',
Wildcard Overrides:
The * wildcard in the config applies to all environments. Place it last to avoid unintended overrides:
'environments' => [
'production' => ['queue:work'],
'*' => ['queue:work', 'cache:clear'], // Applies to all, including production
],
Fix: Reorder or use explicit environment lists.
Case Sensitivity:
Command names and environments are case-sensitive. Ensure APP_ENV=Production (uppercase) matches the config key production (lowercase).
Fix: Standardize environment names (e.g., .env.example):
APP_ENV=local
Command Aliases:
The package checks the base command name (e.g., migrate for migrate:fresh). Aliases like migrate:reset are treated as separate commands.
Fix: Explicitly list aliases in the config:
'environments' => [
'local' => ['migrate', 'migrate:fresh', 'db:seed'],
],
Testing Locally:
Accidentally blocking tinker or serve in local can break development. Double-check the local environment list:
'local' => ['*'], // Allow all commands (use cautiously)
Check Blocked Commands:
Enable debug mode in config/command-banner.php:
'debug' => env('COMMAND_BANNER_DEBUG', false),
Set COMMAND_BANNER_DEBUG=true in .env to log blocked commands to storage/logs/laravel.log.
Bypass for Testing: Temporarily disable the banner in tests by mocking the service provider:
$this->app->singleton(Halilcosdu\LaravelCommandBanner\CommandBannerServiceProvider::class, function () {
return new class extends Halilcosdu\LaravelCommandBanner\CommandBannerServiceProvider {
public function register() { /* Empty */ }
};
});
Environment Variable Overrides:
Use php artisan with --env to test specific environments:
php artisan migrate --env=staging
Custom Blockers: Add logic to dynamically restrict commands based on user roles or time:
use Halilcosdu\LaravelCommandBanner\Contracts\CommandBanner;
$banner->addBlocker(function ($command, $environment) {
return Auth::user()->isAdmin() ? false : true; // Block non-admins
});
Whitelist Mode: Invert the logic to allow only specified commands (default is deny):
'mode' => 'whitelist', // Requires package version >= 1.2.0
Logging Blocked Attempts:
Extend the CommandBlocked event to log to a custom table or external service:
Event::listen(CommandBlocked::class, function ($event) {
\App\Models\CommandAudit::create([
'command' => $event->command,
'environment' => $event->environment,
'ip' => request()->ip(),
]);
});
How can I help you explore Laravel packages today?