Composer Version Change
This commit is contained in:
+246
@@ -0,0 +1,246 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console;
|
||||
|
||||
use Doctrine\DBAL\Schema\Column;
|
||||
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
|
||||
use Doctrine\DBAL\Schema\Index;
|
||||
use Doctrine\DBAL\Schema\Table;
|
||||
use Illuminate\Database\ConnectionResolverInterface;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
|
||||
#[AsCommand(name: 'db:table')]
|
||||
class TableCommand extends DatabaseInspectionCommand
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'db:table
|
||||
{table? : The name of the table}
|
||||
{--database= : The database connection}
|
||||
{--json : Output the table information as JSON}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Display information about the given database table';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle(ConnectionResolverInterface $connections)
|
||||
{
|
||||
if (! $this->ensureDependenciesExist()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
$connection = $connections->connection($this->input->getOption('database'));
|
||||
|
||||
$schema = $connection->getDoctrineSchemaManager();
|
||||
|
||||
$this->registerTypeMappings($schema->getDatabasePlatform());
|
||||
|
||||
$table = $this->argument('table') ?: $this->components->choice(
|
||||
'Which table would you like to inspect?',
|
||||
collect($schema->listTables())->flatMap(fn (Table $table) => [$table->getName()])->toArray()
|
||||
);
|
||||
|
||||
if (! $schema->tablesExist([$table])) {
|
||||
return $this->components->warn("Table [{$table}] doesn't exist.");
|
||||
}
|
||||
|
||||
$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('<fg=green;options=bold>'.$table['name'].'</>');
|
||||
$this->components->twoColumnDetail('Columns', $table['columns']);
|
||||
|
||||
if ($size = $table['size']) {
|
||||
$this->components->twoColumnDetail('Size', number_format($size / 1024 / 1024, 2).'MiB');
|
||||
}
|
||||
|
||||
$this->newLine();
|
||||
|
||||
if ($columns->isNotEmpty()) {
|
||||
$this->components->twoColumnDetail('<fg=green;options=bold>Column</>', 'Type');
|
||||
|
||||
$columns->each(function ($column) {
|
||||
$this->components->twoColumnDetail(
|
||||
$column['column'].' <fg=gray>'.$column['attributes']->implode(', ').'</>',
|
||||
($column['default'] ? '<fg=gray>'.$column['default'].'</> ' : '').''.$column['type'].''
|
||||
);
|
||||
});
|
||||
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
if ($indexes->isNotEmpty()) {
|
||||
$this->components->twoColumnDetail('<fg=green;options=bold>Index</>');
|
||||
|
||||
$indexes->each(function ($index) {
|
||||
$this->components->twoColumnDetail(
|
||||
$index['name'].' <fg=gray>'.$index['columns']->implode(', ').'</>',
|
||||
$index['attributes']->implode(', ')
|
||||
);
|
||||
});
|
||||
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
if ($foreignKeys->isNotEmpty()) {
|
||||
$this->components->twoColumnDetail('<fg=green;options=bold>Foreign Key</>', 'On Update / On Delete');
|
||||
|
||||
$foreignKeys->each(function ($foreignKey) {
|
||||
$this->components->twoColumnDetail(
|
||||
$foreignKey['name'].' <fg=gray;options=bold>'.$foreignKey['local_columns']->implode(', ').' references '.$foreignKey['foreign_columns']->implode(', ').' on '.$foreignKey['foreign_table'].'</>',
|
||||
$foreignKey['on_update'].' / '.$foreignKey['on_delete'],
|
||||
);
|
||||
});
|
||||
|
||||
$this->newLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user