|
<?php |
|
|
|
/** |
|
* ================================================================= |
|
* Laravel Project Init |
|
* ================================================================= |
|
* |
|
* A powerful command to kickstart new Laravel projects. |
|
* Command: project:init |
|
* |
|
* Author: @macarthuror |
|
* |
|
*/ |
|
|
|
namespace App\Console\Commands; |
|
|
|
use Illuminate\Console\Command; |
|
use Illuminate\Support\Facades\File; |
|
use Illuminate\Support\Facades\Artisan; |
|
use Illuminate\Support\Facades\DB; |
|
|
|
class InitProjectCommand extends Command |
|
{ |
|
/** |
|
* The name and signature of the console command. |
|
* |
|
* @var string |
|
*/ |
|
protected $signature = 'project:init |
|
{--force : Force overwrite existing .env file} |
|
{--db-connection=sqlite : Database connection type (sqlite, mysql)} |
|
{--no-seed : Skip running seeders}'; |
|
|
|
/** |
|
* The console command description. |
|
* |
|
* @var string |
|
*/ |
|
protected $description = 'Initialize a new project: create .env, generate key, setup database, and run migrations with seeders (Development only - cannot run in production)'; |
|
|
|
/** |
|
* Execute the console command. |
|
*/ |
|
public function handle() |
|
{ |
|
// Prevent running in production environment |
|
if (app()->environment('production')) { |
|
$this->error('❌ This command cannot be run in production environment for security reasons.'); |
|
$this->error('Please run this command only in local, testing'); |
|
return self::FAILURE; |
|
} |
|
|
|
$this->info('🚀 Starting project initialization...'); |
|
$this->newLine(); |
|
|
|
// Additional safety checks |
|
if (!$this->option('force') && $this->hasExistingData()) { |
|
if (!$this->confirm('⚠️ This operation may overwrite existing data. Are you sure you want to continue?')) { |
|
$this->info('Operation cancelled.'); |
|
return self::SUCCESS; |
|
} |
|
} |
|
|
|
// Check if .env exists |
|
if (File::exists(base_path('.env')) && !$this->option('force')) { |
|
if (!$this->confirm('The .env file already exists. Do you want to overwrite it?')) { |
|
$this->info('Skipping .env file creation.'); |
|
goto skipEnv; |
|
} |
|
} |
|
|
|
// Create .env file from .env.example |
|
$this->createEnvFile(); |
|
|
|
skipEnv: |
|
|
|
// Generate application key |
|
$this->generateAppKey(); |
|
|
|
// Setup database |
|
$this->setupDatabase(); |
|
|
|
// Run migrations |
|
$this->runMigrations(); |
|
|
|
// Run seeders (unless --no-seed is specified) |
|
if (!$this->option('no-seed')) { |
|
$this->runSeeders(); |
|
} |
|
|
|
$this->newLine(); |
|
$this->info('✅ Project initialization completed successfully!'); |
|
$this->info('Your application is ready to use.'); |
|
|
|
return self::SUCCESS; |
|
} |
|
|
|
/** |
|
* Create .env file from .env.example |
|
*/ |
|
protected function createEnvFile() |
|
{ |
|
$this->info('📄 Creating .env file from .env.example...'); |
|
|
|
if (!File::exists(base_path('.env.example'))) { |
|
$this->error('.env.example file not found!'); |
|
return; |
|
} |
|
|
|
File::copy(base_path('.env.example'), base_path('.env')); |
|
$this->info('✓ .env file created successfully'); |
|
} |
|
|
|
/** |
|
* Generate application key |
|
*/ |
|
protected function generateAppKey() |
|
{ |
|
$this->info('🔑 Generating application key...'); |
|
|
|
Artisan::call('key:generate', ['--force' => true]); |
|
|
|
$this->info('✓ Application key generated successfully'); |
|
} |
|
|
|
/** |
|
* Setup database based on connection type |
|
*/ |
|
protected function setupDatabase() |
|
{ |
|
$dbConnection = $this->option('db-connection'); |
|
|
|
$this->info("🗄️ Setting up {$dbConnection} database..."); |
|
|
|
if ($dbConnection === 'sqlite') { |
|
$this->setupSqliteDatabase(); |
|
} elseif ($dbConnection === 'mysql') { |
|
$this->setupMysqlDatabase(); |
|
} else { |
|
$this->warn("Database connection '{$dbConnection}' not specifically handled, proceeding with default configuration."); |
|
} |
|
} |
|
|
|
/** |
|
* Setup SQLite database |
|
*/ |
|
protected function setupSqliteDatabase() |
|
{ |
|
$databasePath = database_path('database.sqlite'); |
|
|
|
if (!File::exists($databasePath)) { |
|
File::put($databasePath, ''); |
|
$this->info('✓ SQLite database file created at: database/database.sqlite'); |
|
} else { |
|
$this->info('✓ SQLite database file already exists'); |
|
} |
|
|
|
// Update .env file to use SQLite |
|
$this->updateEnvFile([ |
|
'DB_CONNECTION' => 'sqlite', |
|
]); |
|
} |
|
|
|
/** |
|
* Setup MySQL database configuration |
|
*/ |
|
protected function setupMysqlDatabase() |
|
{ |
|
$host = $this->ask('Database host', '127.0.0.1'); |
|
$port = $this->ask('Database port', '3306'); |
|
$database = $this->ask('Database name', 'laravel'); |
|
$username = $this->ask('Database username', 'root'); |
|
$password = $this->secret('Database password'); |
|
|
|
// Update .env file with MySQL configuration |
|
$this->updateEnvFile([ |
|
'DB_CONNECTION' => 'mysql', |
|
'DB_HOST' => $host, |
|
'DB_PORT' => $port, |
|
'DB_DATABASE' => $database, |
|
'DB_USERNAME' => $username, |
|
'DB_PASSWORD' => $password, |
|
]); |
|
|
|
$this->info('✓ MySQL database configuration updated'); |
|
} |
|
|
|
/** |
|
* Update .env file with new values |
|
*/ |
|
protected function updateEnvFile(array $values) |
|
{ |
|
$envPath = base_path('.env'); |
|
$envContent = File::get($envPath); |
|
|
|
foreach ($values as $key => $value) { |
|
$pattern = "/^{$key}=.*$/m"; |
|
$replacement = "{$key}={$value}"; |
|
|
|
if (preg_match($pattern, $envContent)) { |
|
$envContent = preg_replace($pattern, $replacement, $envContent); |
|
} else { |
|
$envContent .= "\n{$replacement}"; |
|
} |
|
} |
|
|
|
File::put($envPath, $envContent); |
|
} |
|
|
|
/** |
|
* Run database migrations |
|
*/ |
|
protected function runMigrations() |
|
{ |
|
$this->info('📊 Running database migrations...'); |
|
|
|
try { |
|
// Test database connection first |
|
DB::connection()->getPdo(); |
|
|
|
Artisan::call('migrate', ['--force' => true]); |
|
|
|
$this->info('✓ Database migrations completed successfully'); |
|
} catch (\Exception $e) { |
|
$this->error('Database connection failed: ' . $e->getMessage()); |
|
$this->error('Please check your database configuration and try again.'); |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
/** |
|
* Run database seeders |
|
*/ |
|
protected function runSeeders() |
|
{ |
|
$this->info('🌱 Running database seeders...'); |
|
|
|
try { |
|
Artisan::call('db:seed', ['--force' => true]); |
|
|
|
$this->info('✓ Database seeders completed successfully'); |
|
} catch (\Exception $e) { |
|
$this->warn('Seeders failed: ' . $e->getMessage()); |
|
$this->warn('This is not critical - your application will still work.'); |
|
} |
|
} |
|
|
|
/** |
|
* Check if there's existing data that could be overwritten |
|
*/ |
|
protected function hasExistingData(): bool |
|
{ |
|
// Check if .env file exists |
|
$hasEnv = File::exists(base_path('.env')); |
|
|
|
// Check if database file exists and has content |
|
$hasDatabase = false; |
|
if (File::exists(database_path('database.sqlite'))) { |
|
$hasDatabase = File::size(database_path('database.sqlite')) > 0; |
|
} |
|
|
|
return $hasEnv || $hasDatabase; |
|
} |
|
} |