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(''.$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('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(); } } }