From 47a4eb41bfbe3344c7c001b2e5c027952446320e Mon Sep 17 00:00:00 2001 From: James Brooks Date: Tue, 2 Aug 2022 22:06:25 +0100 Subject: [PATCH] [9.x] New `db:show`, `db:table` and `db:monitor` commands (#43367) * wip * wip * wip * wip * wip * wip * Create `AbstractDatabaseCommand` * wip * Change return type of connection count methods * Add `db:monitor` * Move dbal check * Formatting * Opt-in to expensive operations * Apply fixes from StyleCI * Ask for table * Rename variable * Change how getTableSize works * Make `--max` optional in `db:monitor` * wip * Standardise headings * make `db:monitor` use an argument for databases * Use option again * Move composer to abstract * Add composer * Apply fixes from StyleCI * Update src/Illuminate/Database/Console/MonitorCommand.php Co-authored-by: bastien-phi * formatting * Apply fixes from StyleCI Co-authored-by: Joe Dixon Co-authored-by: StyleCI Bot Co-authored-by: Dries Vints Co-authored-by: bastien-phi Co-authored-by: Taylor Otwell --- .../Console/DatabaseInspectionCommand.php | 196 +++++++++++++++ .../Database/Console/MonitorCommand.php | 151 +++++++++++ .../Database/Console/ShowCommand.php | 185 ++++++++++++++ .../Database/Console/TableCommand.php | 238 ++++++++++++++++++ .../Database/Events/DatabaseBusy.php | 32 +++ .../Foundation/Console/ShowModelCommand.php | 81 +----- .../Providers/ArtisanServiceProvider.php | 39 ++- 7 files changed, 851 insertions(+), 71 deletions(-) create mode 100644 src/Illuminate/Database/Console/DatabaseInspectionCommand.php create mode 100644 src/Illuminate/Database/Console/MonitorCommand.php create mode 100644 src/Illuminate/Database/Console/ShowCommand.php create mode 100644 src/Illuminate/Database/Console/TableCommand.php create mode 100644 src/Illuminate/Database/Events/DatabaseBusy.php diff --git a/src/Illuminate/Database/Console/DatabaseInspectionCommand.php b/src/Illuminate/Database/Console/DatabaseInspectionCommand.php new file mode 100644 index 000000000000..1125d0384103 --- /dev/null +++ b/src/Illuminate/Database/Console/DatabaseInspectionCommand.php @@ -0,0 +1,196 @@ +composer = $composer ?? $this->laravel->make(Composer::class); + } + + /** + * Get a human-readable platform name for the given platform. + * + * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + * @param string $database + * @return string + */ + protected function getPlatformName(AbstractPlatform $platform, $database) + { + return match (class_basename($platform)) { + 'MySQLPlatform' => 'MySQL <= 5', + 'MySQL57Platform' => 'MySQL 5.7', + 'MySQL80Platform' => 'MySQL 8', + 'PostgreSQL100Platform', 'PostgreSQLPlatform' => 'Postgres', + 'SqlitePlatform' => 'SQLite', + 'SQLServerPlatform' => 'SQL Server', + 'SQLServer2012Platform' => 'SQL Server 2012', + default => $database, + }; + } + + /** + * Get the size of a table in bytes. + * + * @param \Illuminate\Database\ConnectionInterface $connection + * @param string $table + * @return int|null + */ + protected function getTableSize(ConnectionInterface $connection, string $table) + { + return match (true) { + $connection instanceof MySqlConnection => $this->getMySQLTableSize($connection, $table), + $connection instanceof PostgresConnection => $this->getPostgresTableSize($connection, $table), + $connection instanceof SQLiteConnection => $this->getSqliteTableSize($connection, $table), + default => null, + }; + } + + /** + * Get the size of a MySQL table in bytes. + * + * @param \Illuminate\Database\ConnectionInterface $connection + * @param string $table + * @return mixed + */ + protected function getMySQLTableSize(ConnectionInterface $connection, string $table) + { + return $connection->selectOne('SELECT (data_length + index_length) AS size FROM information_schema.TABLES WHERE table_schema = ? AND table_name = ?', [ + $connection->getDatabaseName(), + $table, + ])->size; + } + + /** + * Get the size of a Postgres table in bytes. + * + * @param \Illuminate\Database\ConnectionInterface $connection + * @param string $table + * @return mixed + */ + protected function getPostgresTableSize(ConnectionInterface $connection, string $table) + { + return $connection->selectOne('SELECT pg_total_relation_size(?) AS size;', [ + $table, + ])->size; + } + + /** + * Get the size of a SQLite table in bytes. + * + * @param \Illuminate\Database\ConnectionInterface $connection + * @param string $table + * @return mixed + */ + protected function getSqliteTableSize(ConnectionInterface $connection, string $table) + { + return $connection->selectOne('SELECT SUM(pgsize) FROM dbstat WHERE name=?', [ + $table, + ])->size; + } + + /** + * Get the number of open connections for a database. + * + * @param \Illuminate\Database\ConnectionInterface $connection + * @return null + */ + protected function getConnectionCount(ConnectionInterface $connection) + { + return match (class_basename($connection)) { + 'MySqlConnection' => (int) $connection->selectOne($connection->raw('show status where variable_name = "threads_connected"'))->Value, + 'PostgresConnection' => (int) $connection->selectOne('select count(*) as connections from pg_stat_activity')->connections, + 'SqlServerConnection' => (int) $connection->selectOne('SELECT COUNT(*) connections FROM sys.dm_exec_sessions WHERE status = ?', ['running'])->connections, + default => null, + }; + } + + /** + * Get the connection configuration details for the given connection. + * + * @param string $database + * @return array + */ + protected function getConfigFromDatabase($database) + { + $database ??= config('database.default'); + + return Arr::except(config('database.connections.'.$database), ['password']); + } + + /** + * Ensure the dependencies for the database commands are available. + * + * @return int|null + */ + protected function ensureDependenciesExist() + { + if (! interface_exists('Doctrine\DBAL\Driver')) { + if (! $this->components->confirm('Displaying model information requires the Doctrine DBAL (doctrine/dbal) package. Would you like to install it?')) { + return 1; + } + + return $this->installDependencies(); + } + } + + /** + * Install the command's dependencies. + * + * @return void + * + * @throws \Symfony\Component\Process\Exception\ProcessSignaledException + */ + protected function installDependencies() + { + $command = collect($this->composer->findComposer()) + ->push('require doctrine/dbal') + ->implode(' '); + + $process = Process::fromShellCommandline($command, null, null, null, null); + + if ('\\' !== DIRECTORY_SEPARATOR && file_exists('/dev/tty') && is_readable('/dev/tty')) { + try { + $process->setTty(true); + } catch (RuntimeException $e) { + $this->components->warn($e->getMessage()); + } + } + + try { + $process->run(fn ($type, $line) => $this->output->write($line)); + } catch (ProcessSignaledException $e) { + if (extension_loaded('pcntl') && $e->getSignal() !== SIGINT) { + throw $e; + } + } + } +} diff --git a/src/Illuminate/Database/Console/MonitorCommand.php b/src/Illuminate/Database/Console/MonitorCommand.php new file mode 100644 index 000000000000..5d0f3edcbdb2 --- /dev/null +++ b/src/Illuminate/Database/Console/MonitorCommand.php @@ -0,0 +1,151 @@ +connection = $connection; + $this->events = $events; + } + + /** + * Execute the console command. + * + * @return void + */ + public function handle() + { + $databases = $this->parseDatabases($this->option('databases')); + + $this->displayConnections($databases); + + if ($this->option('max')) { + $this->dispatchEvents($databases); + } + } + + /** + * Parse the database into an array of the connections. + * + * @param string $databases + * @return \Illuminate\Support\Collection + */ + protected function parseDatabases($databases) + { + return collect(explode(',', $databases))->map(function ($database) { + if (! $database) { + $database = $this->laravel['config']['database.default']; + } + + $maxConnections = $this->option('max'); + + return [ + 'database' => $database, + 'connections' => $connections = $this->getConnectionCount($this->connection->connection($database)), + 'status' => $maxConnections && $connections >= $maxConnections ? 'ALERT' : 'OK', + ]; + }); + } + + /** + * Display the databases and their connection counts in the console. + * + * @param \Illuminate\Support\Collection $databases + * @return void + */ + protected function displayConnections($databases) + { + $this->newLine(); + + $this->components->twoColumnDetail('Database name', 'Connections'); + + $databases->each(function ($database) { + $status = '['.$database['connections'].'] '.$database['status']; + + $this->components->twoColumnDetail($database['database'], $status); + }); + + $this->newLine(); + } + + /** + * Dispatch the database monitoring events. + * + * @param \Illuminate\Support\Collection $databases + * @return void + */ + protected function dispatchEvents($databases) + { + $databases->each(function ($database) { + if ($database['status'] === 'OK') { + return; + } + + $this->events->dispatch( + new DatabaseBusy( + $database['database'], + $database['connections'] + ) + ); + }); + } +} diff --git a/src/Illuminate/Database/Console/ShowCommand.php b/src/Illuminate/Database/Console/ShowCommand.php new file mode 100644 index 000000000000..125de1cac558 --- /dev/null +++ b/src/Illuminate/Database/Console/ShowCommand.php @@ -0,0 +1,185 @@ + Note: This can be slow on large databases }; + {--views : Show the database views Note: This can be slow on large databases }'; + + /** + * The console command description. + * + * @var string + */ + protected $description = 'Display information about the given database'; + + /** + * Execute the console command. + * + * @param \Illuminate\Database\ConnectionResolverInterface $connections + * @return int + */ + public function handle(ConnectionResolverInterface $connections) + { + $this->ensureDependenciesExist(); + + $connection = $connections->connection($database = $this->input->getOption('database')); + + $schema = $connection->getDoctrineSchemaManager(); + + $data = [ + 'platform' => [ + 'config' => $this->getConfigFromDatabase($database), + 'name' => $this->getPlatformName($schema->getDatabasePlatform(), $database), + 'open_connections' => $this->getConnectionCount($connection), + ], + 'tables' => $this->tables($connection, $schema), + ]; + + if ($this->option('views')) { + $data['views'] = $this->collectViews($connection, $schema); + } + + $this->display($data); + + return 0; + } + + /** + * Get information regarding the tables within the database. + * + * @param \Illuminate\Database\ConnectionInterface $connection + * @param \Doctrine\DBAL\Schema\AbstractSchemaManager $schema + * @return \Illuminate\Support\Collection + */ + protected function tables(ConnectionInterface $connection, AbstractSchemaManager $schema) + { + return collect($schema->listTables())->map(fn (Table $table, $index) => [ + 'table' => $table->getName(), + 'size' => $this->getTableSize($connection, $table->getName()), + 'rows' => $this->option('counts') ? $connection->table($table->getName())->count() : null, + 'engine' => rescue(fn () => $table->getOption('engine')), + 'comment' => $table->getComment(), + ]); + } + + /** + * Get information regarding the views within the database. + * + * @param \Illuminate\Database\ConnectionInterface $connection + * @param \Doctrine\DBAL\Schema\AbstractSchemaManager $schema + * @return \Illuminate\Support\Collection + */ + protected function collectViews(ConnectionInterface $connection, AbstractSchemaManager $schema) + { + return collect($schema->listViews()) + ->reject(fn (View $view) => str($view->getName()) + ->startsWith(['pg_catalog', 'information_schema', 'spt_'])) + ->map(fn (View $view) => [ + 'view' => $view->getName(), + 'rows' => $connection->table($view->getName())->count(), + ]); + } + + /** + * Render the database information. + * + * @param array $data + * @return void + */ + protected function display(array $data) + { + $this->option('json') ? $this->displayJson($data) : $this->displayForCli($data); + } + + /** + * Render the database information as JSON. + * + * @param array $data + * @return void + */ + protected function displayJson(array $data) + { + $this->output->writeln(json_encode($data)); + } + + /** + * Render the database information formatted for the CLI. + * + * @param array $data + * @return void + */ + protected function displayForCli(array $data) + { + $platform = $data['platform']; + $tables = $data['tables']; + $views = $data['views'] ?? null; + + $this->newLine(); + + $this->components->twoColumnDetail(''.$platform['name'].''); + $this->components->twoColumnDetail('Database', Arr::get($platform['config'], 'database')); + $this->components->twoColumnDetail('Host', Arr::get($platform['config'], 'host')); + $this->components->twoColumnDetail('Port', Arr::get($platform['config'], 'port')); + $this->components->twoColumnDetail('Username', Arr::get($platform['config'], 'username')); + $this->components->twoColumnDetail('URL', Arr::get($platform['config'], 'url')); + $this->components->twoColumnDetail('Open Connections', $platform['open_connections']); + $this->components->twoColumnDetail('Tables', $tables->count()); + + if ($tableSizeSum = $tables->sum('size')) { + $this->components->twoColumnDetail('Total Size', number_format($tableSizeSum / 1024 / 1024, 2).'Mb'); + } + + $this->newLine(); + + if ($tables->isNotEmpty()) { + $this->components->twoColumnDetail('Table', 'Size (Mb)'.($this->option('counts') ? ' / Rows' : '')); + + $tables->each(function ($table) { + if ($tableSize = $table['size']) { + $tableSize = number_format($tableSize / 1024 / 1024, 2); + } + + $this->components->twoColumnDetail( + $table['table'].($this->output->isVerbose() ? ' '.$table['engine'].'' : null), + ($tableSize ? $tableSize : '—').($this->option('counts') ? ' / '.number_format($table['rows']).'' : '') + ); + + if ($this->output->isVerbose()) { + if ($table['comment']) { + $this->components->bulletList([ + $table['comment'], + ]); + } + } + }); + + $this->newLine(); + } + + if ($views && $views->isNotEmpty()) { + $this->components->twoColumnDetail('View', 'Rows'); + + $views->each(fn ($view) => $this->components->twoColumnDetail($view['view'], number_format($view['rows']))); + + $this->newLine(); + } + } +} diff --git a/src/Illuminate/Database/Console/TableCommand.php b/src/Illuminate/Database/Console/TableCommand.php new file mode 100644 index 000000000000..7cc99162f721 --- /dev/null +++ b/src/Illuminate/Database/Console/TableCommand.php @@ -0,0 +1,238 @@ +ensureDependenciesExist(); + + $connection = $connections->connection($this->input->getOption('database')); + + $schema = $connection->getDoctrineSchemaManager(); + + $table = $this->argument('table') ?: $this->components->choice( + 'Which table would you like to inspect?', + collect($schema->listTables())->flatMap(fn (Table $table) => [$table->getName()])->toArray() + ); + + $table = $schema->listTableDetails($table); + + $columns = $this->columns($table); + $indexes = $this->indexes($table); + $foreignKeys = $this->foreignKeys($table); + + $data = [ + 'table' => [ + 'name' => $table->getName(), + 'columns' => $columns->count(), + 'size' => $this->getTableSize($connection, $table->getName()), + ], + 'columns' => $columns, + 'indexes' => $indexes, + 'foreign_keys' => $foreignKeys, + ]; + + $this->display($data); + + return 0; + } + + /** + * Get the information regarding the table's columns. + * + * @param \Doctrine\DBAL\Schema\Table $table + * @return \Illuminate\Support\Collection + */ + protected function columns(Table $table) + { + return collect($table->getColumns())->map(fn (Column $column) => [ + 'column' => $column->getName(), + 'attributes' => $this->getAttributesForColumn($column), + 'default' => $column->getDefault(), + 'type' => $column->getType()->getName(), + ]); + } + + /** + * Get the attributes for a table column. + * + * @param \Doctrine\DBAL\Schema\Column $column + * @return \Illuminate\Support\Collection + */ + protected function getAttributesForColumn(Column $column) + { + return collect([ + $column->getAutoincrement() ? 'autoincrement' : null, + 'type' => $column->getType()->getName(), + $column->getUnsigned() ? 'unsigned' : null, + ! $column->getNotNull() ? 'nullable' : null, + ])->filter(); + } + + /** + * Get the information regarding the table's indexes. + * + * @param \Doctrine\DBAL\Schema\Table $table + * @return \Illuminate\Support\Collection + */ + protected function indexes(Table $table) + { + return collect($table->getIndexes())->map(fn (Index $index) => [ + 'name' => $index->getName(), + 'columns' => collect($index->getColumns()), + 'attributes' => $this->getAttributesForIndex($index), + ]); + } + + /** + * Get the attributes for a table index. + * + * @param \Doctrine\DBAL\Schema\Index $index + * @return \Illuminate\Support\Collection + */ + protected function getAttributesForIndex(Index $index) + { + return collect([ + 'compound' => count($index->getColumns()) > 1, + 'unique' => $index->isUnique(), + 'primary' => $index->isPrimary(), + ])->filter()->keys()->map(fn ($attribute) => Str::lower($attribute)); + } + + /** + * Get the information regarding the table's foreign keys. + * + * @param \Doctrine\DBAL\Schema\Table $table + * @return \Illuminate\Support\Collection + */ + protected function foreignKeys(Table $table) + { + return collect($table->getForeignKeys())->map(fn (ForeignKeyConstraint $foreignKey) => [ + 'name' => $foreignKey->getName(), + 'local_table' => $table->getName(), + 'local_columns' => collect($foreignKey->getLocalColumns()), + 'foreign_table' => $foreignKey->getForeignTableName(), + 'foreign_columns' => collect($foreignKey->getForeignColumns()), + 'on_update' => Str::lower(rescue(fn () => $foreignKey->getOption('onUpdate'), 'N/A')), + 'on_delete' => Str::lower(rescue(fn () => $foreignKey->getOption('onDelete'), 'N/A')), + ]); + } + + /** + * Render the table information. + * + * @param array $data + * @return void + */ + protected function display(array $data) + { + $this->option('json') ? $this->displayJson($data) : $this->displayForCli($data); + } + + /** + * Render the table information as JSON. + * + * @param array $data + * @return void + */ + protected function displayJson(array $data) + { + $this->output->writeln(json_encode($data)); + } + + /** + * Render the table information formatted for the CLI. + * + * @param array $data + * @return void + */ + protected function displayForCli(array $data) + { + [$table, $columns, $indexes, $foreignKeys] = [ + $data['table'], $data['columns'], $data['indexes'], $data['foreign_keys'], + ]; + + $this->newLine(); + + $this->components->twoColumnDetail(''.$table['name'].''); + $this->components->twoColumnDetail('Columns', $table['columns']); + + if ($size = $table['size']) { + $this->components->twoColumnDetail('Size', number_format($size / 1024 / 1024, 2).'Mb'); + } + + $this->newLine(); + + if ($columns->isNotEmpty()) { + $this->components->twoColumnDetail('Column', 'Type'); + + $columns->each(function ($column) { + $this->components->twoColumnDetail( + $column['column'].' '.$column['attributes']->implode(', ').'', + ($column['default'] ? ''.$column['default'].' ' : '').''.$column['type'].'' + ); + }); + + $this->newLine(); + } + + if ($indexes->isNotEmpty()) { + $this->components->twoColumnDetail('Index'); + + $indexes->each(function ($index) { + $this->components->twoColumnDetail( + $index['name'].' '.$index['columns']->implode(', ').'', + $index['attributes']->implode(', ') + ); + }); + + $this->newLine(); + } + + if ($foreignKeys->isNotEmpty()) { + $this->components->twoColumnDetail('Foreign Key', 'On Update / On Delete'); + + $foreignKeys->each(function ($foreignKey) { + $this->components->twoColumnDetail( + $foreignKey['name'].' '.$foreignKey['local_columns']->implode(', ').' references '.$foreignKey['foreign_columns']->implode(', ').' on '.$foreignKey['foreign_table'].'', + $foreignKey['on_update'].' / '.$foreignKey['on_delete'], + ); + }); + + $this->newLine(); + } + } +} diff --git a/src/Illuminate/Database/Events/DatabaseBusy.php b/src/Illuminate/Database/Events/DatabaseBusy.php new file mode 100644 index 000000000000..8e903a907535 --- /dev/null +++ b/src/Illuminate/Database/Events/DatabaseBusy.php @@ -0,0 +1,32 @@ +connectionName = $connectionName; + $this->connections = $connections; + } +} diff --git a/src/Illuminate/Foundation/Console/ShowModelCommand.php b/src/Illuminate/Foundation/Console/ShowModelCommand.php index 0fb101fa5093..5a01b574cdc3 100644 --- a/src/Illuminate/Foundation/Console/ShowModelCommand.php +++ b/src/Illuminate/Foundation/Console/ShowModelCommand.php @@ -8,21 +8,18 @@ use Doctrine\DBAL\Types\DecimalType; use Illuminate\Console\Command; use Illuminate\Contracts\Container\BindingResolutionException; +use Illuminate\Database\Console\DatabaseInspectionCommand; use Illuminate\Database\Eloquent\Relations\Relation; -use Illuminate\Support\Composer; use Illuminate\Support\Str; use ReflectionClass; use ReflectionMethod; use SplFileObject; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Process\Exception\ProcessSignaledException; -use Symfony\Component\Process\Exception\RuntimeException; -use Symfony\Component\Process\Process; use UnitEnum; #[AsCommand(name: 'model:show')] -class ShowModelCommand extends Command +class ShowModelCommand extends DatabaseInspectionCommand { /** * The console command name. @@ -58,13 +55,6 @@ class ShowModelCommand extends Command {--database= : The database connection to use} {--json : Output the model as JSON}'; - /** - * The Composer instance. - * - * @var \Illuminate\Support\Composer - */ - protected $composer; - /** * The methods that can be called in a model to indicate a relation. * @@ -84,19 +74,6 @@ class ShowModelCommand extends Command 'morphedByMany', ]; - /** - * Create a new command instance. - * - * @param \Illuminate\Support\Composer $composer - * @return void - */ - public function __construct(Composer $composer) - { - parent::__construct(); - - $this->composer = $composer; - } - /** * Execute the console command. * @@ -104,13 +81,7 @@ public function __construct(Composer $composer) */ public function handle() { - if (! interface_exists('Doctrine\DBAL\Driver')) { - if (! $this->components->confirm('Displaying model information requires the Doctrine DBAL (doctrine/dbal) package. Would you like to install it?')) { - return 1; - } - - return $this->installDependencies(); - } + $this->ensureDependenciesExist(); $class = $this->qualifyModel($this->argument('model')); @@ -175,9 +146,10 @@ protected function getVirtualAttributes($model, $columns) $class = new ReflectionClass($model); return collect($class->getMethods()) - ->reject(fn (ReflectionMethod $method) => $method->isStatic() - || $method->isAbstract() - || $method->getDeclaringClass()->getName() !== get_class($model) + ->reject( + fn (ReflectionMethod $method) => $method->isStatic() + || $method->isAbstract() + || $method->getDeclaringClass()->getName() !== get_class($model) ) ->mapWithKeys(function (ReflectionMethod $method) use ($model) { if (preg_match('/^get(.*)Attribute$/', $method->getName(), $matches) === 1) { @@ -214,9 +186,10 @@ protected function getRelations($model) { return collect(get_class_methods($model)) ->map(fn ($method) => new ReflectionMethod($model, $method)) - ->reject(fn (ReflectionMethod $method) => $method->isStatic() - || $method->isAbstract() - || $method->getDeclaringClass()->getName() !== get_class($model) + ->reject( + fn (ReflectionMethod $method) => $method->isStatic() + || $method->isAbstract() + || $method->getDeclaringClass()->getName() !== get_class($model) ) ->filter(function (ReflectionMethod $method) { $file = new SplFileObject($method->getFileName()); @@ -489,36 +462,4 @@ protected function qualifyModel(string $model) ? $rootNamespace.'Models\\'.$model : $rootNamespace.$model; } - - /** - * Install the command's dependencies. - * - * @return void - * - * @throws \Symfony\Component\Process\Exception\ProcessSignaledException - */ - protected function installDependencies() - { - $command = collect($this->composer->findComposer()) - ->push('require doctrine/dbal') - ->implode(' '); - - $process = Process::fromShellCommandline($command, null, null, null, null); - - if ('\\' !== DIRECTORY_SEPARATOR && file_exists('/dev/tty') && is_readable('/dev/tty')) { - try { - $process->setTty(true); - } catch (RuntimeException $e) { - $this->components->warn($e->getMessage()); - } - } - - try { - $process->run(fn ($type, $line) => $this->output->write($line)); - } catch (ProcessSignaledException $e) { - if (extension_loaded('pcntl') && $e->getSignal() !== SIGINT) { - throw $e; - } - } - } } diff --git a/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php b/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php index 10dcec6138d3..95c43de541a1 100755 --- a/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php +++ b/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php @@ -16,9 +16,12 @@ use Illuminate\Database\Console\DbCommand; use Illuminate\Database\Console\DumpCommand; use Illuminate\Database\Console\Factories\FactoryMakeCommand; +use Illuminate\Database\Console\MonitorCommand as DatabaseMonitorCommand; use Illuminate\Database\Console\PruneCommand; use Illuminate\Database\Console\Seeds\SeedCommand; use Illuminate\Database\Console\Seeds\SeederMakeCommand; +use Illuminate\Database\Console\ShowCommand; +use Illuminate\Database\Console\TableCommand as DatabaseTableCommand; use Illuminate\Database\Console\WipeCommand; use Illuminate\Foundation\Console\AboutCommand; use Illuminate\Foundation\Console\CastMakeCommand; @@ -102,7 +105,10 @@ class ArtisanServiceProvider extends ServiceProvider implements DeferrableProvid 'ConfigCache' => ConfigCacheCommand::class, 'ConfigClear' => ConfigClearCommand::class, 'Db' => DbCommand::class, + 'DbMonitor' => DatabaseMonitorCommand::class, 'DbPrune' => PruneCommand::class, + 'DbShow' => ShowCommand::class, + 'DbTable' => DatabaseTableCommand::class, 'DbWipe' => WipeCommand::class, 'Down' => DownCommand::class, 'Environment' => EnvironmentCommand::class, @@ -193,7 +199,8 @@ class ArtisanServiceProvider extends ServiceProvider implements DeferrableProvid public function register() { $this->registerCommands(array_merge( - $this->commands, $this->devCommands + $this->commands, + $this->devCommands )); } @@ -374,6 +381,16 @@ protected function registerDbCommand() $this->app->singleton(DbCommand::class); } + /** + * Register the command. + * + * @return void + */ + protected function registerDbMonitorCommand() + { + $this->app->singleton(DatabaseMonitorCommand::class); + } + /** * Register the command. * @@ -384,6 +401,26 @@ protected function registerDbPruneCommand() $this->app->singleton(PruneCommand::class); } + /** + * Register the command. + * + * @return void + */ + protected function registerDbShowCommand() + { + $this->app->singleton(ShowCommand::class); + } + + /** + * Register the command. + * + * @return void + */ + protected function registerDbTableCommand() + { + $this->app->singleton(DatabaseTableCommand::class); + } + /** * Register the command. *