Laravel Zero transforms Laravel from a web framework into a powerful command-line application platform. By stripping away web-specific components and adding CLI-focused features, Laravel Zero enables developers to build sophisticated console applications with Laravel's elegant syntax and robust ecosystem, perfect for automation scripts, development tools, and system utilities.
Table Of Contents
- Understanding Laravel Zero's Philosophy
- Getting Started with Laravel Zero
- Advanced CLI Interactions
- Building a Real-World Tool: Code Generator
- Package Management and Distribution
- Testing Laravel Zero Applications
- Performance and Optimization
- Conclusion
- Related Articles
Understanding Laravel Zero's Philosophy
Laravel Zero reimagines Laravel for the command line, maintaining the framework's core principles while optimizing for CLI environments. It provides a minimal, fast foundation that includes only essential components, allowing developers to add features as needed. This approach results in lightweight, single-file executables that can run anywhere PHP is available.
The framework excels at building tools that developers actually want to use – package managers, deployment scripts, code generators, and system administration utilities. With Laravel Zero, you can create professional CLI applications that rival those built with specialized CLI frameworks.
Getting Started with Laravel Zero
Installation and project setup are streamlined for rapid development:
# Install Laravel Zero via Composer
composer create-project --prefer-dist laravel-zero/laravel-zero awesome-cli
cd awesome-cli
# Explore the project structure
tree -L 2
Laravel Zero's structure is optimized for CLI applications:
<?php
// app/Commands/AwesomeCommand.php
namespace App\Commands;
use LaravelZero\Framework\Commands\Command;
use Illuminate\Support\Facades\Http;
class AwesomeCommand extends Command
{
protected $signature = 'awesome {name} {--format=json}';
protected $description = 'Generate awesome greetings';
public function handle(): int
{
$name = $this->argument('name');
$format = $this->option('format');
$greeting = $this->generateGreeting($name);
if ($format === 'json') {
$this->line(json_encode([
'greeting' => $greeting,
'timestamp' => now()->toISOString(),
'format' => 'json'
], JSON_PRETTY_PRINT));
} else {
$this->info("🎉 {$greeting}");
}
return self::SUCCESS;
}
private function generateGreeting(string $name): string
{
$greetings = [
"Hello, awesome {$name}!",
"Greetings, magnificent {$name}!",
"Salutations, incredible {$name}!",
"Hey there, fantastic {$name}!"
];
return $greetings[array_rand($greetings)];
}
}
// config/commands.php - Register commands
return [
'default' => 'awesome',
'paths' => [app_path('Commands')],
'add' => [
// Additional commands
],
'hidden' => [
// Hidden commands
],
'remove' => [
// Commands to remove
],
];
You can also leverage Laravel Events and Listeners: Building Decoupled Applications for decoupled workflows, apply Advanced Eloquent Techniques and Optimizations in Laravel within your commands, and ensure reliability with Laravel Testing: Unit, Feature, and Integration Tests.
Advanced CLI Interactions
Create rich, interactive command-line experiences:
<?php
namespace App\Commands;
use LaravelZero\Framework\Commands\Command;
use Illuminate\Support\Collection;
class InteractiveSetupCommand extends Command
{
protected $signature = 'setup {--force}';
protected $description = 'Interactive application setup';
public function handle(): int
{
$this->displayHeader();
if (!$this->option('force') && !$this->confirmSetup()) {
return self::FAILURE;
}
$config = $this->gatherConfiguration();
$this->createConfigFile($config);
$this->installDependencies($config);
$this->finalizeSetup();
return self::SUCCESS;
}
private function displayHeader(): void
{
$this->line('');
$this->line('<fg=cyan>╔══════════════════════════════════════╗</>');
$this->line('<fg=cyan>║</> <fg=white;options=bold> Awesome CLI Setup Wizard </> <fg=cyan>║</>');
$this->line('<fg=cyan>╚══════════════════════════════════════╝</>');
$this->line('');
}
private function confirmSetup(): bool
{
return $this->confirm(
'This will configure your application. Continue?',
true
);
}
private function gatherConfiguration(): array
{
$config = [];
// Text input with validation
$config['app_name'] = $this->askWithValidation(
'Application name',
'required|string|min:3|max:50',
'My Awesome App'
);
// Choice selection
$config['environment'] = $this->choice(
'Select environment',
['development', 'staging', 'production'],
'development'
);
// Multiple choice with search
$config['features'] = $this->multipleChoice(
'Select features to enable',
[
'logging' => 'Advanced Logging',
'cache' => 'Caching System',
'database' => 'Database Support',
'api' => 'HTTP API Client',
'notifications' => 'Notifications',
]
);
// Secret input
if (in_array('api', $config['features'])) {
$config['api_key'] = $this->secret('Enter API key');
}
// Numeric input with bounds
$config['timeout'] = $this->askNumeric(
'Request timeout (seconds)',
30,
1,
300
);
// Advanced configuration
if ($this->confirm('Configure advanced options?', false)) {
$config = array_merge($config, $this->gatherAdvancedConfig());
}
return $config;
}
private function multipleChoice(string $question, array $choices): array
{
$this->line("<fg=yellow>{$question}</>");
$selected = [];
foreach ($choices as $key => $label) {
if ($this->confirm(" Enable {$label}?", false)) {
$selected[] = $key;
}
}
return $selected;
}
private function askNumeric(string $question, int $default, int $min, int $max): int
{
do {
$value = (int) $this->ask("{$question} [{$min}-{$max}]", $default);
if ($value < $min || $value > $max) {
$this->error("Value must be between {$min} and {$max}");
continue;
}
return $value;
} while (true);
}
private function gatherAdvancedConfig(): array
{
return [
'debug_mode' => $this->confirm('Enable debug mode?', false),
'log_level' => $this->choice('Log level', [
'debug', 'info', 'warning', 'error'
], 'info'),
'max_memory' => $this->ask('Memory limit (MB)', '256'),
];
}
private function createConfigFile(array $config): void
{
$this->task('Creating configuration file', function () use ($config) {
$configPath = base_path('config/app-config.json');
file_put_contents(
$configPath,
json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
);
sleep(1); // Simulate work
return true;
});
}
private function installDependencies(array $config): void
{
if (empty($config['features'])) {
return;
}
$this->info('Installing selected features...');
$progressBar = $this->output->createProgressBar(count($config['features']));
$progressBar->start();
foreach ($config['features'] as $feature) {
$this->installFeature($feature);
$progressBar->advance();
usleep(500000); // Simulate installation time
}
$progressBar->finish();
$this->line('');
}
private function installFeature(string $feature): void
{
// Simulate feature installation
$packages = [
'logging' => 'monolog/monolog',
'cache' => 'symfony/cache',
'database' => 'illuminate/database',
'api' => 'guzzlehttp/guzzle',
'notifications' => 'laravel/slack-notification-channel',
];
// In real implementation, you would run composer commands
// or download/configure actual dependencies
}
private function finalizeSetup(): void
{
$this->line('');
$this->info('✅ Setup completed successfully!');
$this->line('');
$this->line('<fg=green>Next steps:</>');
$this->line(' • Run <fg=yellow>./app-name --help</> to see available commands');
$this->line(' • Edit <fg=yellow>config/app-config.json</> to modify settings');
$this->line(' • Check <fg=yellow>README.md</> for documentation');
$this->line('');
}
}
Building a Real-World Tool: Code Generator
Let's create a practical code generator tool:
<?php
namespace App\Commands;
use LaravelZero\Framework\Commands\Command;
use Illuminate\Support\Str;
use Illuminate\Filesystem\Filesystem;
class GenerateCommand extends Command
{
protected $signature = 'generate {type} {name} {--namespace=App} {--force}';
protected $description = 'Generate code files from templates';
private Filesystem $files;
private array $generators = [
'class' => 'generateClass',
'interface' => 'generateInterface',
'trait' => 'generateTrait',
'enum' => 'generateEnum',
'test' => 'generateTest',
'config' => 'generateConfig',
];
public function __construct(Filesystem $files)
{
parent::__construct();
$this->files = $files;
}
public function handle(): int
{
$type = $this->argument('type');
$name = $this->argument('name');
if (!isset($this->generators[$type])) {
$this->error("Unknown generator type: {$type}");
$this->line('Available types: ' . implode(', ', array_keys($this->generators)));
return self::FAILURE;
}
$method = $this->generators[$type];
return $this->$method($name);
}
private function generateClass(string $name): int
{
$className = Str::studly($name);
$namespace = $this->option('namespace');
$path = $this->getOutputPath($className, 'php');
if ($this->files->exists($path) && !$this->option('force')) {
if (!$this->confirm("File {$path} exists. Overwrite?")) {
return self::FAILURE;
}
}
$template = $this->loadTemplate('class');
$content = $this->processTemplate($template, [
'namespace' => $namespace,
'className' => $className,
'timestamp' => now()->format('Y-m-d H:i:s'),
'author' => $this->getUserName(),
]);
$this->ensureDirectoryExists(dirname($path));
$this->files->put($path, $content);
$this->info("✅ Class created: {$path}");
return self::SUCCESS;
}
private function generateInterface(string $name): int
{
$interfaceName = Str::studly($name) . 'Interface';
$namespace = $this->option('namespace');
$path = $this->getOutputPath($interfaceName, 'php');
$methods = $this->gatherInterfaceMethods();
$template = $this->loadTemplate('interface');
$content = $this->processTemplate($template, [
'namespace' => $namespace,
'interfaceName' => $interfaceName,
'methods' => $this->generateMethodSignatures($methods),
'timestamp' => now()->format('Y-m-d H:i:s'),
]);
$this->ensureDirectoryExists(dirname($path));
$this->files->put($path, $content);
$this->info("✅ Interface created: {$path}");
return self::SUCCESS;
}
private function generateTest(string $name): int
{
$testName = Str::studly($name) . 'Test';
$namespace = 'Tests\\Unit';
$path = $this->getOutputPath($testName, 'php', 'tests/Unit');
// Interactive test configuration
$testType = $this->choice('Test type', ['unit', 'feature', 'integration'], 'unit');
$withMocks = $this->confirm('Include mock examples?', false);
$withDataProvider = $this->confirm('Include data provider?', false);
$template = $this->loadTemplate('test');
$content = $this->processTemplate($template, [
'namespace' => $namespace,
'testName' => $testName,
'testType' => $testType,
'withMocks' => $withMocks,
'withDataProvider' => $withDataProvider,
'className' => str_replace('Test', '', $testName),
]);
$this->ensureDirectoryExists(dirname($path));
$this->files->put($path, $content);
$this->info("✅ Test created: {$path}");
$this->line("Run with: <fg=yellow>phpunit {$path}</>");
return self::SUCCESS;
}
private function generateConfig(string $name): int
{
$configName = Str::snake($name);
$path = $this->getOutputPath($configName, 'php', 'config');
$configType = $this->choice('Configuration type', [
'array' => 'PHP Array',
'class' => 'Configuration Class',
'env' => 'Environment Variables',
], 'array');
$template = $this->loadTemplate("config.{$configType}");
$content = $this->processTemplate($template, [
'configName' => $configName,
'className' => Str::studly($configName) . 'Config',
'variables' => $this->gatherConfigVariables(),
]);
$this->ensureDirectoryExists(dirname($path));
$this->files->put($path, $content);
$this->info("✅ Configuration created: {$path}");
return self::SUCCESS;
}
private function gatherInterfaceMethods(): array
{
$methods = [];
$this->info('Define interface methods (press enter with empty name to finish):');
while (true) {
$methodName = $this->ask('Method name');
if (empty($methodName)) {
break;
}
$returnType = $this->ask('Return type', 'mixed');
$parameters = $this->gatherMethodParameters();
$methods[] = [
'name' => $methodName,
'returnType' => $returnType,
'parameters' => $parameters,
];
}
return $methods;
}
private function gatherMethodParameters(): array
{
$parameters = [];
while (true) {
$paramName = $this->ask('Parameter name (empty to finish)');
if (empty($paramName)) {
break;
}
$paramType = $this->ask('Parameter type', 'mixed');
$hasDefault = $this->confirm('Has default value?', false);
$defaultValue = $hasDefault ? $this->ask('Default value', 'null') : null;
$parameters[] = [
'name' => $paramName,
'type' => $paramType,
'default' => $defaultValue,
];
}
return $parameters;
}
private function gatherConfigVariables(): array
{
$variables = [];
$this->info('Define configuration variables:');
while (true) {
$varName = $this->ask('Variable name (empty to finish)');
if (empty($varName)) {
break;
}
$varType = $this->choice('Variable type', [
'string', 'int', 'bool', 'array', 'float'
], 'string');
$defaultValue = $this->ask('Default value', 'null');
$description = $this->ask('Description', '');
$variables[] = [
'name' => $varName,
'type' => $varType,
'default' => $defaultValue,
'description' => $description,
];
}
return $variables;
}
private function generateMethodSignatures(array $methods): string
{
$signatures = [];
foreach ($methods as $method) {
$params = [];
foreach ($method['parameters'] as $param) {
$paramStr = $param['type'] . ' $' . $param['name'];
if ($param['default'] !== null) {
$paramStr .= ' = ' . $param['default'];
}
$params[] = $paramStr;
}
$signature = sprintf(
' public function %s(%s): %s;',
$method['name'],
implode(', ', $params),
$method['returnType']
);
$signatures[] = $signature;
}
return implode("\n\n", $signatures);
}
private function loadTemplate(string $templateName): string
{
$templatePath = resource_path("templates/{$templateName}.stub");
if (!$this->files->exists($templatePath)) {
throw new \RuntimeException("Template not found: {$templatePath}");
}
return $this->files->get($templatePath);
}
private function processTemplate(string $template, array $variables): string
{
$content = $template;
foreach ($variables as $key => $value) {
if (is_array($value)) {
$value = $this->processArrayVariable($value);
}
$content = str_replace("{{ {$key} }}", $value, $content);
}
return $content;
}
private function processArrayVariable(array $data): string
{
// Convert array data to appropriate string representation
return var_export($data, true);
}
private function getOutputPath(string $name, string $extension, string $directory = 'app'): string
{
return base_path("{$directory}/{$name}.{$extension}");
}
private function ensureDirectoryExists(string $path): void
{
if (!$this->files->isDirectory($path)) {
$this->files->makeDirectory($path, 0755, true);
}
}
private function getUserName(): string
{
return trim(shell_exec('git config user.name 2>/dev/null')) ?: 'Unknown';
}
}
// Template files (store in resources/templates/)
// resources/templates/class.stub
/*
<?php
namespace {{ namespace }};
/**
* Class {{ className }}
*
* Generated on: {{ timestamp }}
* Author: {{ author }}
*/
class {{ className }}
{
public function __construct()
{
//
}
}
*/
// resources/templates/interface.stub
/*
<?php
namespace {{ namespace }};
/**
* Interface {{ interfaceName }}
*
* Generated on: {{ timestamp }}
*/
interface {{ interfaceName }}
{
{{ methods }}
}
*/
Package Management and Distribution
Create distributable Laravel Zero applications:
<?php
namespace App\Commands;
use LaravelZero\Framework\Commands\Command;
use Illuminate\Support\Facades\Http;
class BuildCommand extends Command
{
protected $signature = 'build {--optimize} {--target=all}';
protected $description = 'Build distributable application';
public function handle(): int
{
$this->info('🔨 Building application...');
$this->optimizeApplication();
$this->createDistributableFiles();
$this->generateDocumentation();
if ($this->option('target') === 'all' || $this->option('target') === 'phar') {
$this->buildPharArchive();
}
$this->info('✅ Build completed successfully!');
return self::SUCCESS;
}
private function optimizeApplication(): void
{
if (!$this->option('optimize')) {
return;
}
$this->task('Optimizing application', function () {
// Clear caches
$this->call('cache:clear');
// Optimize autoloader
shell_exec('composer dump-autoload --optimize --no-dev');
// Remove development dependencies
shell_exec('composer install --no-dev --optimize-autoloader');
return true;
});
}
private function createDistributableFiles(): void
{
$this->task('Creating distribution files', function () {
$buildDir = base_path('build');
if (!is_dir($buildDir)) {
mkdir($buildDir, 0755, true);
}
// Copy application files
$this->copyFiles([
'app' => 'build/app',
'config' => 'build/config',
'vendor' => 'build/vendor',
'bootstrap' => 'build/bootstrap',
]);
// Create executable script
$this->createExecutableScript();
return true;
});
}
private function copyFiles(array $paths): void
{
foreach ($paths as $source => $destination) {
if (is_dir($source)) {
shell_exec("cp -r {$source} {$destination}");
} elseif (file_exists($source)) {
copy($source, $destination);
}
}
}
private function createExecutableScript(): void
{
$script = <<<'SCRIPT'
#!/usr/bin/env php
<?php
if (file_exists(__DIR__.'/vendor/autoload.php')) {
require __DIR__.'/vendor/autoload.php';
} else {
require __DIR__.'/../../autoload.php';
}
$app = new LaravelZero\Framework\Application(
dirname(__DIR__)
);
$kernel = $app->make(LaravelZero\Framework\Kernel::class);
$status = $kernel->handle(
$input = new Symfony\Component\Console\Input\ArgvInput,
new Symfony\Component\Console\Output\ConsoleOutput
);
$kernel->terminate($input, $status);
exit($status);
SCRIPT;
file_put_contents('build/app-executable', $script);
chmod('build/app-executable', 0755);
}
private function buildPharArchive(): void
{
$this->task('Building PHAR archive', function () {
$pharPath = base_path('build/app.phar');
if (file_exists($pharPath)) {
unlink($pharPath);
}
$phar = new \Phar($pharPath, 0, 'app.phar');
$phar->setSignatureAlgorithm(\Phar::SHA1);
$phar->startBuffering();
// Add application files
$this->addDirectoryToPhar($phar, 'build/app', 'app');
$this->addDirectoryToPhar($phar, 'build/vendor', 'vendor');
$this->addDirectoryToPhar($phar, 'build/config', 'config');
$this->addDirectoryToPhar($phar, 'build/bootstrap', 'bootstrap');
// Set stub
$phar->setStub($this->getPharStub());
$phar->stopBuffering();
chmod($pharPath, 0755);
return true;
});
}
private function addDirectoryToPhar(\Phar $phar, string $directory, string $localName): void
{
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($directory)
);
foreach ($iterator as $file) {
if ($file->isFile()) {
$relativePath = str_replace($directory . '/', '', $file->getPathname());
$phar->addFile($file->getPathname(), $localName . '/' . $relativePath);
}
}
}
private function getPharStub(): string
{
return <<<'STUB'
#!/usr/bin/env php
<?php
Phar::mapPhar('app.phar');
require 'phar://app.phar/bootstrap/app.php';
__HALT_COMPILER();
STUB;
}
private function generateDocumentation(): void
{
$this->task('Generating documentation', function () {
$commands = $this->getAvailableCommands();
$readme = $this->generateReadme($commands);
file_put_contents('build/README.md', $readme);
return true;
});
}
private function getAvailableCommands(): array
{
$commands = [];
foreach (glob(app_path('Commands/*.php')) as $file) {
$className = pathinfo($file, PATHINFO_FILENAME);
$class = "App\\Commands\\{$className}";
if (class_exists($class)) {
$reflection = new \ReflectionClass($class);
$instance = $reflection->newInstance();
if (property_exists($instance, 'signature') && property_exists($instance, 'description')) {
$commands[] = [
'name' => $instance->getName(),
'signature' => $instance->signature,
'description' => $instance->description,
];
}
}
}
return $commands;
}
private function generateReadme(array $commands): string
{
$appName = config('app.name', 'Laravel Zero App');
$version = config('app.version', '1.0.0');
$readme = "# {$appName}\n\n";
$readme .= "Version: {$version}\n\n";
$readme .= "## Installation\n\n";
$readme .= "Download the `app.phar` file and make it executable:\n\n";
$readme .= "```bash\n";
$readme .= "chmod +x app.phar\n";
$readme .= "./app.phar --help\n";
$readme .= "```\n\n";
$readme .= "## Available Commands\n\n";
foreach ($commands as $command) {
$readme .= "### {$command['name']}\n\n";
$readme .= "{$command['description']}\n\n";
$readme .= "```bash\n";
$readme .= "./{$appName} {$command['signature']}\n";
$readme .= "```\n\n";
}
return $readme;
}
}
Testing Laravel Zero Applications
Implement comprehensive testing strategies:
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Support\Facades\Storage;
class CodeGeneratorTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();
// Setup test filesystem
Storage::fake('local');
// Create mock templates directory
$this->createMockTemplates();
}
public function test_generates_class_successfully(): void
{
$this->artisan('generate class TestClass --namespace=App\\Models')
->expectsQuestion('File exists. Overwrite?', false)
->assertExitCode(0)
->expectsOutput('✅ Class created:');
}
public function test_interactive_interface_generation(): void
{
$this->artisan('generate interface PaymentProcessor')
->expectsQuestion('Method name', 'process')
->expectsQuestion('Return type', 'bool')
->expectsQuestion('Parameter name (empty to finish)', 'amount')
->expectsQuestion('Parameter type', 'float')
->expectsQuestion('Has default value?', false)
->expectsQuestion('Parameter name (empty to finish)', '')
->expectsQuestion('Method name', '')
->assertExitCode(0);
}
public function test_handles_invalid_generator_type(): void
{
$this->artisan('generate invalid TestName')
->assertExitCode(1)
->expectsOutput('Unknown generator type: invalid');
}
public function test_build_command_creates_distribution(): void
{
$this->artisan('build --optimize')
->assertExitCode(0)
->expectsOutput('🔨 Building application...')
->expectsOutput('✅ Build completed successfully!');
// Assert build directory exists
$this->assertTrue(is_dir(base_path('build')));
// Assert executable was created
$this->assertTrue(file_exists(base_path('build/app-executable')));
}
public function test_setup_command_interactive_flow(): void
{
$this->artisan('setup')
->expectsConfirmation('This will configure your application. Continue?', 'yes')
->expectsQuestion('Application name', 'Test App')
->expectsChoice('Select environment', 'development')
->expectsConfirmation('Enable Advanced Logging?', 'yes')
->expectsConfirmation('Enable Caching System?', 'no')
->expectsConfirmation('Configure advanced options?', 'no')
->assertExitCode(0);
// Assert config file was created
$this->assertTrue(file_exists(base_path('config/app-config.json')));
}
private function createMockTemplates(): void
{
$templates = [
'class' => '<?php\n\nnamespace {{ namespace }};\n\nclass {{ className }}\n{\n //\n}',
'interface' => '<?php\n\nnamespace {{ namespace }};\n\ninterface {{ interfaceName }}\n{\n{{ methods }}\n}',
'test' => '<?php\n\nnamespace {{ namespace }};\n\nuse PHPUnit\\Framework\\TestCase;\n\nclass {{ testName }} extends TestCase\n{\n //\n}',
];
foreach ($templates as $name => $content) {
$path = resource_path("templates/{$name}.stub");
if (!is_dir(dirname($path))) {
mkdir(dirname($path), 0755, true);
}
file_put_contents($path, $content);
}
}
}
// Unit test for utility classes
namespace Tests\Unit;
use Tests\TestCase;
use App\Services\TemplateProcessor;
class TemplateProcessorTest extends TestCase
{
private TemplateProcessor $processor;
protected function setUp(): void
{
parent::setUp();
$this->processor = new TemplateProcessor();
}
public function test_processes_simple_variables(): void
{
$template = 'Hello {{ name }}, welcome to {{ app }}!';
$variables = ['name' => 'John', 'app' => 'Laravel Zero'];
$result = $this->processor->process($template, $variables);
$this->assertEquals('Hello John, welcome to Laravel Zero!', $result);
}
public function test_handles_array_variables(): void
{
$template = 'Methods: {{ methods }}';
$variables = ['methods' => ['create', 'update', 'delete']];
$result = $this->processor->process($template, $variables);
$this->assertStringContainsString('create', $result);
$this->assertStringContainsString('update', $result);
$this->assertStringContainsString('delete', $result);
}
public function test_ignores_missing_variables(): void
{
$template = 'Hello {{ name }}, {{ missing }} variable';
$variables = ['name' => 'John'];
$result = $this->processor->process($template, $variables);
$this->assertEquals('Hello John, {{ missing }} variable', $result);
}
}
Performance and Optimization
Optimize Laravel Zero applications for speed:
<?php
namespace App\Commands;
use LaravelZero\Framework\Commands\Command;
use Illuminate\Support\Facades\Cache;
class OptimizeCommand extends Command
{
protected $signature = 'optimize {--clear}';
protected $description = 'Optimize application performance';
public function handle(): int
{
if ($this->option('clear')) {
$this->clearOptimizations();
} else {
$this->runOptimizations();
}
return self::SUCCESS;
}
private function runOptimizations(): void
{
$this->info('🚀 Optimizing application...');
$optimizations = [
'Optimizing configuration' => [$this, 'optimizeConfig'],
'Optimizing routes' => [$this, 'optimizeRoutes'],
'Optimizing autoloader' => [$this, 'optimizeAutoloader'],
'Caching templates' => [$this, 'cacheTemplates'],
'Optimizing dependencies' => [$this, 'optimizeDependencies'],
];
foreach ($optimizations as $description => $callback) {
$this->task($description, $callback);
}
$this->info('✅ Optimization completed!');
}
private function optimizeConfig(): bool
{
// Cache configuration
$this->call('config:cache');
// Remove unused config files
$configFiles = glob(config_path('*.php'));
$usedConfigs = ['app', 'cache', 'logging'];
foreach ($configFiles as $file) {
$basename = basename($file, '.php');
if (!in_array($basename, $usedConfigs)) {
// Move to backup location instead of deleting
rename($file, $file . '.backup');
}
}
return true;
}
private function optimizeRoutes(): bool
{
// For Laravel Zero, optimize command discovery
$commandFiles = glob(app_path('Commands/*.php'));
$commandCache = [];
foreach ($commandFiles as $file) {
$className = basename($file, '.php');
$commandCache[$className] = [
'file' => $file,
'modified' => filemtime($file),
];
}
Cache::forever('command_cache', $commandCache);
return true;
}
private function optimizeAutoloader(): bool
{
shell_exec('composer dump-autoload --optimize');
return true;
}
private function cacheTemplates(): bool
{
$templateDir = resource_path('templates');
if (!is_dir($templateDir)) {
return true;
}
$templates = glob($templateDir . '/*.stub');
$templateCache = [];
foreach ($templates as $template) {
$name = basename($template, '.stub');
$templateCache[$name] = file_get_contents($template);
}
Cache::forever('template_cache', $templateCache);
return true;
}
private function optimizeDependencies(): bool
{
// Remove development dependencies in production
if (app()->environment('production')) {
shell_exec('composer install --no-dev --optimize-autoloader');
}
return true;
}
private function clearOptimizations(): void
{
$this->info('🧹 Clearing optimizations...');
$operations = [
'Clearing configuration cache' => function () {
$this->call('config:clear');
return true;
},
'Clearing command cache' => function () {
Cache::forget('command_cache');
return true;
},
'Clearing template cache' => function () {
Cache::forget('template_cache');
return true;
},
'Restoring config backups' => function () {
$backups = glob(config_path('*.php.backup'));
foreach ($backups as $backup) {
rename($backup, str_replace('.backup', '', $backup));
}
return true;
},
];
foreach ($operations as $description => $callback) {
$this->task($description, $callback);
}
$this->info('✅ Optimizations cleared!');
}
}
// Performance monitoring
class PerformanceProfiler
{
private float $startTime;
private int $startMemory;
private array $checkpoints = [];
public function start(): void
{
$this->startTime = microtime(true);
$this->startMemory = memory_get_usage(true);
}
public function checkpoint(string $name): void
{
$this->checkpoints[$name] = [
'time' => microtime(true) - $this->startTime,
'memory' => memory_get_usage(true) - $this->startMemory,
'peak_memory' => memory_get_peak_usage(true),
];
}
public function report(): array
{
return [
'total_time' => microtime(true) - $this->startTime,
'total_memory' => memory_get_usage(true) - $this->startMemory,
'peak_memory' => memory_get_peak_usage(true),
'checkpoints' => $this->checkpoints,
];
}
}
Conclusion
Laravel Zero transforms Laravel into a powerful CLI application framework that maintains the elegance and functionality developers love while optimizing for command-line environments. By leveraging Laravel's ecosystem within a CLI context, developers can build sophisticated tools that rival those created with specialized CLI frameworks.
The framework's strength lies in its ability to make complex CLI applications feel natural to Laravel developers. From interactive setup wizards to distributable PHAR archives, Laravel Zero provides all the tools needed to create professional command-line applications. Whether building internal development tools, system utilities, or standalone applications, Laravel Zero offers the perfect balance of power and simplicity.
Add Comment
No comments yet. Be the first to comment!