DbCommand.php
TLDR
The DbCommand.php
file in the Illuminate\Database\Console
namespace is a class that extends the Command
class. It provides a console command to start a new database CLI session. The command accepts an optional argument for specifying the database connection and options for connecting to either a read or write connection.
Methods
handle
This method executes the console command. It retrieves the connection configuration and checks if the host is specified. If not, it displays an error message and instructions for using the --read
and --write
options. It then creates a new Process
instance and runs the database client command with the appropriate arguments and environment variables. The output of the command is written to the console.
getConnection
This method retrieves the database connection configuration based on the provided connection argument or the default connection. It checks if the connection configuration is empty and throws an UnexpectedValueException
if it is. It also parses the connection URL if present. If the --read
option is used, it merges the read
connection configuration. If the --write
option is used, it merges the write
connection configuration. The resulting connection configuration is returned.
commandArguments
This method takes the connection configuration as an argument and returns the arguments for the database client command based on the driver. The driver name is converted to uppercase and appended with "Arguments". For example, if the driver is "mysql", the method that will be called is getMysqlArguments
.
commandEnvironment
This method takes the connection configuration as an argument and returns the environment variables for the database client command based on the driver. The driver name is converted to uppercase and appended with "Environment". For example, if the driver is "pgsql", the method that will be called is getPgsqlEnvironment
.
getCommand
This method takes the connection configuration as an argument and returns the database client command based on the driver. It uses an array mapping of drivers to command names.
getMysqlArguments
This method takes the connection configuration as an argument and returns the arguments for the MySQL CLI. It merges the host, port, and username arguments, and includes optional arguments such as password, unix_socket, and charset.
getPgsqlArguments
This method takes the connection configuration as an argument and returns the arguments for the Postgres CLI. It only includes the database argument.
getSqliteArguments
This method takes the connection configuration as an argument and returns the arguments for the SQLite CLI. It only includes the database argument.
getSqlsrvArguments
This method takes the connection configuration as an argument and returns the arguments for the SQL Server CLI. It merges the optional arguments such as database, username, password, and host.
getPgsqlEnvironment
This method takes the connection configuration as an argument and returns the environment variables for the Postgres CLI. It merges the optional arguments such as username, host, port, and password.
getOptionalArguments
This method takes an array of arguments and the connection configuration as arguments and returns an array of optional arguments based on the connection configuration. It filters out the arguments that are empty.
<?php
namespace Illuminate\Database\Console;
use Illuminate\Console\Command;
use Illuminate\Support\ConfigurationUrlParser;
use Symfony\Component\Process\Process;
use UnexpectedValueException;
class DbCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'db {connection? : The database connection that should be used}
{--read : Connect to the read connection}
{--write : Connect to the write connection}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Start a new database CLI session';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$connection = $this->getConnection();
if (! isset($connection['host']) && $connection['driver'] !== 'sqlite') {
$this->components->error('No host specified for this database connection.');
$this->line(' Use the <options=bold>[--read]</> and <options=bold>[--write]</> options to specify a read or write connection.');
$this->newLine();
return Command::FAILURE;
}
(new Process(
array_merge([$this->getCommand($connection)], $this->commandArguments($connection)),
null,
$this->commandEnvironment($connection)
))->setTimeout(null)->setTty(true)->mustRun(function ($type, $buffer) {
$this->output->write($buffer);
});
return 0;
}
/**
* Get the database connection configuration.
*
* @return array
*
* @throws \UnexpectedValueException
*/
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}].");
}
if (! empty($connection['url'])) {
$connection = (new ConfigurationUrlParser)->parseConfiguration($connection);
}
if ($this->option('read')) {
if (is_array($connection['read']['host'])) {
$connection['read']['host'] = $connection['read']['host'][0];
}
$connection = array_merge($connection, $connection['read']);
} elseif ($this->option('write')) {
if (is_array($connection['write']['host'])) {
$connection['write']['host'] = $connection['write']['host'][0];
}
$connection = array_merge($connection, $connection['write']);
}
return $connection;
}
/**
* Get the arguments for the database client command.
*
* @param array $connection
* @return array
*/
public function commandArguments(array $connection)
{
$driver = ucfirst($connection['driver']);
return $this->{"get{$driver}Arguments"}($connection);
}
/**
* Get the environment variables for the database client command.
*
* @param array $connection
* @return array|null
*/
public function commandEnvironment(array $connection)
{
$driver = ucfirst($connection['driver']);
if (method_exists($this, "get{$driver}Environment")) {
return $this->{"get{$driver}Environment"}($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 getMysqlArguments(array $connection)
{
return array_merge([
'--host='.$connection['host'],
'--port='.$connection['port'],
'--user='.$connection['username'],
], $this->getOptionalArguments([
'password' => '--password='.$connection['password'],
'unix_socket' => '--socket='.($connection['unix_socket'] ?? ''),
'charset' => '--default-character-set='.($connection['charset'] ?? ''),
], $connection), [$connection['database']]);
}
/**
* Get the arguments for the Postgres CLI.
*
* @param array $connection
* @return array
*/
protected function getPgsqlArguments(array $connection)
{
return [$connection['database']];
}
/**
* Get the arguments for the SQLite CLI.
*
* @param array $connection
* @return array
*/
protected function getSqliteArguments(array $connection)
{
return [$connection['database']];
}
/**
* Get the arguments for the SQL Server CLI.
*
* @param array $connection
* @return array
*/
protected function getSqlsrvArguments(array $connection)
{
return array_merge(...$this->getOptionalArguments([
'database' => ['-d', $connection['database']],
'username' => ['-U', $connection['username']],
'password' => ['-P', $connection['password']],
'host' => ['-S', 'tcp:'.$connection['host']
.($connection['port'] ? ','.$connection['port'] : ''), ],
], $connection));
}
/**
* Get the environment variables for the Postgres CLI.
*
* @param array $connection
* @return array|null
*/
protected function getPgsqlEnvironment(array $connection)
{
return array_merge(...$this->getOptionalArguments([
'username' => ['PGUSER' => $connection['username']],
'host' => ['PGHOST' => $connection['host']],
'port' => ['PGPORT' => $connection['port']],
'password' => ['PGPASSWORD' => $connection['password']],
], $connection));
}
/**
* Get the optional arguments based on the connection configuration.
*
* @param array $args
* @param array $connection
* @return array
*/
protected function getOptionalArguments(array $args, array $connection)
{
return array_values(array_filter($args, function ($key) use ($connection) {
return ! empty($connection[$key]);
}, ARRAY_FILTER_USE_KEY));
}
}