diff --git a/src/Illuminate/Database/Console/DbCommand.php b/src/Illuminate/Database/Console/DbCommand.php new file mode 100644 index 000000000000..5a50049773bb --- /dev/null +++ b/src/Illuminate/Database/Console/DbCommand.php @@ -0,0 +1,195 @@ +getConnection(); + + (new Process( + array_merge([$this->getCommand($connection)], $this->getArgs($connection)), + null, $this->getEnv($connection) + ))->setTimeout(null)->setTty(true)->mustRun(function ($type, $buffer) { + $this->output->write($buffer); + }); + + return 0; + } + + /** + * Get the database connection configuration. + * + * @return array + */ + public function getConnection() + { + $connection = $this->laravel['config']['database.connections.'. + (($db = $this->argument('connection')) ?? $this->laravel['config']['database.default']) + ]; + + if (empty($connection)) { + throw new UnexpectedValueException("Invalid database connection: [{$db}]."); + } + + return $connection; + } + + /** + * Get the arguments for the database client command. + * + * @param array $connection + * @return array + */ + public function getArgs(array $connection) + { + $driver = ucfirst($connection['driver']); + + return $this->{"get{$driver}Args"}($connection); + } + + /** + * Get the environmental variables for the database client command. + * + * @param array $connection + * @return array|null + */ + public function getEnv(array $connection) + { + $driver = ucfirst($connection['driver']); + + if (method_exists($this, "get{$driver}Env")) { + return $this->{"get{$driver}Env"}($connection); + } + + return null; + } + + /** + * Get the database client command to run. + * + * @param array $connection + * @return string + */ + public function getCommand(array $connection) + { + return [ + 'mysql' => 'mysql', + 'pgsql' => 'psql', + 'sqlite' => 'sqlite3', + 'sqlsrv' => 'sqlcmd', + ][$connection['driver']]; + } + + /** + * Get the arguments for the mysql CLI. + * + * @param array $connection + * @return array + */ + protected function getMysqlArgs(array $connection) + { + return array_merge([ + '--host='.$connection['host'], + '--port='.$connection['port'], + '--user='.$connection['username'], + ], $this->buildOptionalArguments([ + 'password' => '--password='.$connection['password'], + 'unix_socket' => '--socket='.$connection['unix_socket'], + 'charset' => '--default-character-set='.$connection['charset'], + ], $connection), [$connection['database']]); + } + + /** + * Get the arguments for the pgsql CLI. + * + * @param array $connection + * @return array + */ + protected function getPgsqlArgs(array $connection) + { + return [$connection['database']]; + } + + /** + * Get the arguments for the sqlite CLI. + * + * @param array $connection + * @return array + */ + protected function getSqliteArgs(array $connection) + { + return [$connection['database']]; + } + + /** + * Get the arguments for the SQL Server CLI. + * + * @param array $connection + * @return array + */ + protected function getSqlsrvArgs(array $connection) + { + return $this->buildOptionalArguments([ + 'database' => '-d '.$connection['database'], + 'username' => '-U '.$connection['username'], + 'password' => '-P '.$connection['password'], + 'host' => '-S tcp:'.$connection['host'] + .($connection['port'] ? ','.$connection['port'] : ''), + ], $connection); + } + + /** + * Get the environmental variables for the pgsql CLI. + * + * @param array $connection + * @return array|null + */ + protected function getPgsqlEnv(array $connection) + { + return array_merge(...$this->buildOptionalArguments([ + 'username' => ['PGUSER' => $connection['username']], + 'host' => ['PGHOST' => $connection['host']], + 'port' => ['PGPORT' => $connection['port']], + 'password' => ['PGPASSWORD' => $connection['password']], + ], $connection)); + } + + /** + * Build optional arguments based on the connection configuration. + * + * @param array $args + * @param array $connection + * @return array + */ + protected function buildOptionalArguments(array $args, array $connection) + { + return array_values(array_filter($args, function ($key) use ($connection) { + return ! empty($connection[$key]); + }, ARRAY_FILTER_USE_KEY)); + } +} diff --git a/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php b/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php index dc82ba1df83c..c4d31671075d 100755 --- a/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php +++ b/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php @@ -10,6 +10,7 @@ use Illuminate\Console\Scheduling\ScheduleRunCommand; use Illuminate\Console\Scheduling\ScheduleWorkCommand; use Illuminate\Contracts\Support\DeferrableProvider; +use Illuminate\Database\Console\DbCommand; use Illuminate\Database\Console\DumpCommand; use Illuminate\Database\Console\Factories\FactoryMakeCommand; use Illuminate\Database\Console\Seeds\SeedCommand; @@ -88,6 +89,7 @@ class ArtisanServiceProvider extends ServiceProvider implements DeferrableProvid 'ClearResets' => 'command.auth.resets.clear', 'ConfigCache' => 'command.config.cache', 'ConfigClear' => 'command.config.clear', + 'Db' => DbCommand::class, 'DbWipe' => 'command.db.wipe', 'Down' => 'command.down', 'Environment' => 'command.environment', @@ -332,6 +334,16 @@ protected function registerControllerMakeCommand() }); } + /** + * Register the command. + * + * @return void + */ + protected function registerDbCommand() + { + $this->app->singleton(DbCommand::class); + } + /** * Register the command. *