master

laravel/framework

Last updated at: 29/12/2023 09:21

ShowCommand.php

TLDR

The ShowCommand.php file is part of the Illuminate\Database\Console namespace in the Demo Projects project. It is a PHP file that provides a command-line interface (CLI) command called db:show, which displays information about a specified database. The command retrieves information about the database's platform, including configuration, open connections, tables, and (optionally) views. The information can be displayed either as formatted text or as JSON.

Methods

handle

This method executes the db:show command. It retrieves the specified database connection, collects information about the platform and tables, and optionally collects information about views. Finally, it calls the display method to render the collected information.

tables

This method retrieves information about the tables within the connected database. It uses the listTables method from the AbstractSchemaManager class to get a list of Table objects representing the tables. It then maps each Table object to an array containing details such as the table name, size, row count (if the --counts option is enabled), engine, and comment. The method returns a collection of these arrays.

collectViews

This method retrieves information about the views within the connected database. It uses the listViews method from the AbstractSchemaManager class to get a list of View objects representing the views. It filters out system views and maps each remaining View object to an array containing details such as the view name and row count (which is obtained by querying the view with the table method of the connected connection). The method returns a collection of these arrays.

display

This method renders the database information. If the --json option is enabled, it outputs the information as JSON using the writeln method of the output property. Otherwise, it calls the displayForCli method to render the information in a formatted manner.

displayJson

This method takes an array of database information and outputs it as JSON using the writeln method of the output property.

displayForCli

This method takes an array of database information and renders it in a formatted manner for the command-line interface. It retrieves the platform, tables, and (if available) views from the array and uses the components property to display the information in a structured format.

Classes

There are no additional classes in this file.

<?php

namespace Illuminate\Database\Console;

use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\View;
use Illuminate\Database\ConnectionInterface;
use Illuminate\Database\ConnectionResolverInterface;
use Illuminate\Support\Arr;
use Symfony\Component\Console\Attribute\AsCommand;

#[AsCommand(name: 'db:show')]
class ShowCommand extends DatabaseInspectionCommand
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'db:show {--database= : The database connection}
                {--json : Output the database information as JSON}
                {--counts : Show the table row count <bg=red;options=bold> Note: This can be slow on large databases </>};
                {--views : Show the database views <bg=red;options=bold> 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)
    {
        if (! $this->ensureDependenciesExist()) {
            return 1;
        }

        $connection = $connections->connection($database = $this->input->getOption('database'));

        $doctrineConnection = $connection->getDoctrineConnection();
        $schema = $connection->getDoctrineSchemaManager();

        $this->registerTypeMappings($doctrineConnection->getDatabasePlatform());

        $data = [
            'platform' => [
                'config' => $this->getConfigFromDatabase($database),
                'name' => $this->getPlatformName($doctrineConnection->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'), null, false),
            '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('<fg=green;options=bold>'.$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).'MiB');
        }

        $this->newLine();

        if ($tables->isNotEmpty()) {
            $this->components->twoColumnDetail('<fg=green;options=bold>Table</>', 'Size (MiB)'.($this->option('counts') ? ' <fg=gray;options=bold>/</> <fg=yellow;options=bold>Rows</>' : ''));

            $tables->each(function ($table) {
                if ($tableSize = $table['size']) {
                    $tableSize = number_format($tableSize / 1024 / 1024, 2);
                }

                $this->components->twoColumnDetail(
                    $table['table'].($this->output->isVerbose() ? ' <fg=gray>'.$table['engine'].'</>' : null),
                    ($tableSize ? $tableSize : '—').($this->option('counts') ? ' <fg=gray;options=bold>/</> <fg=yellow;options=bold>'.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('<fg=green;options=bold>View</>', '<fg=green;options=bold>Rows</>');

            $views->each(fn ($view) => $this->components->twoColumnDetail($view['view'], number_format($view['rows'])));

            $this->newLine();
        }
    }
}