├── .github └── workflows │ └── php.yml ├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── phpunit.xml ├── src ├── Console │ ├── DbUtilitiesCommand.php │ ├── RuleExportCommend.php │ └── TransExportCommend.php ├── Exports │ ├── Concerns │ │ └── ExcelMacro.php │ ├── DdlExport.php │ ├── ListExport.php │ └── TableExport.php ├── Facades │ ├── CreateView.php │ ├── Table.php │ └── Type.php ├── Helpers │ └── Arr.php ├── Models │ ├── Contracts │ │ ├── ColumnInterface.php │ │ ├── ConstraintInterface.php │ │ ├── IndexInterface.php │ │ ├── ManageViewInterface.php │ │ ├── TableInterface.php │ │ └── TypeInterface.php │ ├── CreateView.php │ ├── Repositories │ │ ├── MysqlColumn.php │ │ ├── MysqlConstraint.php │ │ ├── MysqlIndex.php │ │ ├── MysqlManageView.php │ │ ├── MysqlTable.php │ │ ├── MysqlType.php │ │ ├── PostgresqlColumn.php │ │ ├── PostgresqlConstraint.php │ │ ├── PostgresqlIndex.php │ │ ├── PostgresqlManageView.php │ │ ├── PostgresqlTable.php │ │ └── PostgresqlType.php │ ├── Table.php │ └── Type.php ├── Providers │ └── ServiceProvider.php └── sql │ ├── mysql_create_view.sql │ └── psql_create_view.sql ├── translations ├── en │ └── ddl.php └── ja │ └── ddl.php └── views └── table.blade.php /.github/workflows/php.yml: -------------------------------------------------------------------------------- 1 | name: phpunit 2 | 3 | on: 4 | push: 5 | 6 | jobs: 7 | phpunit: 8 | runs-on: ubuntu-latest 9 | 10 | strategy: 11 | matrix: 12 | php: [7.4,8.0,8.1] 13 | dependency-version: [prefer-lowest, prefer-stable] 14 | 15 | name: PHP ${{ matrix.php }} - ${{ matrix.dependency-version }} 16 | 17 | steps: 18 | - name: Checkout code 19 | uses: actions/checkout@v1 20 | 21 | - name: Setup PHP 22 | uses: shivammathur/setup-php@v2 23 | with: 24 | php-version: ${{ matrix.php }} 25 | 26 | - name: Install dependencies 27 | run: composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction --no-suggest 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | vendor/ 3 | .DS_Store 4 | composer.lock 5 | .phpunit.result.cache -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2010 - 2011 Fuel Development Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # laravel-ddl-export 2 | 3 | Laravel プロジェクトから、テーブル定義書を xlsx 形式でエクスポートします! 4 | 5 | Export Table definition to spreadsheet by artisan command. 6 | 7 | For MySQL, PostgreSQL 8 | 9 | ## Install 10 | 11 | ```bash 12 | $ composer require shibuyakosuke/laravel-ddl-export 13 | ``` 14 | 15 | ## Usage 16 | 17 | Write your migration file with comments. 18 | To add table comment, use [this library](https://github.com/diplodocker/comments-loader). 19 | 20 | ```php 21 | id()->comment('ID'); 38 | $table->string('name')->comment('氏名'); 39 | $table->string('email')->unique()->comment('メールアドレス'); 40 | $table->timestamp('email_verified_at')->nullable()->comment('メール認証日時'); 41 | $table->string('password')->comment('パスワード'); 42 | $table->rememberToken()->comment('リメンバートークン'); 43 | $table->dateTime('created_at')->nullable()->comment('作成日時'); 44 | $table->dateTime('updated_at')->nullable()->comment('更新日時'); 45 | $table->softDeletes()->comment('削除日時'); 46 | $table->tableComment('ユーザー'); 47 | }); 48 | } 49 | }; 50 | ``` 51 | 52 | Run migration before exporting. 53 | 54 | ```bash 55 | $ php artisan migrate 56 | $ php artisan ddl:export 57 | ``` 58 | 59 | ## Export validation rules 60 | 61 | ```bash 62 | $ php artisan ddl:rules 63 | ``` 64 | 65 | output to `/config/rules.php` 66 | 67 | ```php 68 | return [ 69 | 'users' => [ 70 | 'id' => ['integer', 'required'], 71 | 'name' => ['string', 'required', 'max:255'], 72 | 'email' => ['string', 'required', 'max:255'], 73 | 'email_verified_at' => ['date', 'nullable'], 74 | 'password' => ['string', 'required', 'max:255'], 75 | 'remember_token' => ['string', 'nullable', 'max:100'], 76 | 'created_at' => ['date', 'nullable'], 77 | 'updated_at' => ['date', 'nullable'], 78 | 'deleted_at' => ['date', 'nullable'], 79 | ], 80 | ]; 81 | ``` 82 | 83 | ## Export translation file 84 | 85 | ```bash 86 | $ php artisan ddl:trans 87 | ``` 88 | 89 | output to `/resources/lang/ja/columns.php` 90 | 91 | ```php 92 | return [ 93 | 'users' => [ 94 | 'id' => 'ID', 95 | 'name' => '氏名', 96 | 'email' => 'メールアドレス', 97 | 'email_verified_at' => 'メール認証日時', 98 | 'password' => 'パスワード', 99 | 'remember_token' => 'リメンバートークン', 100 | 'created_at' => '作成日時', 101 | 'updated_at' => '更新日時', 102 | 'deleted_at' => '削除日時', 103 | ], 104 | ]; 105 | ``` 106 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "shibuyakosuke/laravel-ddl-export", 3 | "description": "Export Table definition to spreadsheet by artisan command.", 4 | "type": "library", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "ShibuyaKosuke", 9 | "email": "github@shibuyakosuke.com" 10 | } 11 | ], 12 | "require": { 13 | "php": "^7.4 | ^8.0 | ^8.1 | ^8.2", 14 | "laravel/framework": "7.30.4 | ^8.0 | ^9.0 | ^10.0 | ^11.0", 15 | "maatwebsite/excel": "^3.1" 16 | }, 17 | "autoload": { 18 | "psr-4": { 19 | "ShibuyaKosuke\\LaravelDdlExport\\": "src/" 20 | } 21 | }, 22 | "extra": { 23 | "laravel": { 24 | "providers": [ 25 | "ShibuyaKosuke\\LaravelDdlExport\\Providers\\ServiceProvider" 26 | ], 27 | "aliases": { 28 | "Table": "ShibuyaKosuke\\LaravelDdlExport\\Facades\\Table", 29 | "Column": "ShibuyaKosuke\\LaravelDdlExport\\Facades\\Column" 30 | } 31 | } 32 | }, 33 | "require-dev": { 34 | "phpstan/phpstan": "^0.12.85" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | tests 15 | 16 | 17 | 18 | 19 | src/ 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/Console/DbUtilitiesCommand.php: -------------------------------------------------------------------------------- 1 | option('output') ?? 'ddl.xlsx'; 36 | 37 | if (!\Str::endsWith($output, '.xlsx')) { 38 | $output .= '.xlsx'; 39 | } 40 | 41 | CreateView::up(); 42 | 43 | (new DdlExport($this->getOutput()))->store($output); 44 | 45 | $this->output->success('Output: ' . storage_path($output)); 46 | 47 | CreateView::down(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Console/RuleExportCommend.php: -------------------------------------------------------------------------------- 1 | mapWithKeys(function (TableInterface $table) { 42 | return [ 43 | $table->name => $table->columns 44 | ->map(static function (ColumnInterface $column) { 45 | /** @var ConstraintInterface $constraint */ 46 | $foreign = ($constraint = $column->foreign) ? 47 | sprintf( 48 | 'exists:%s,%s', 49 | $constraint->referenced_table_name, 50 | $constraint->referenced_column_name 51 | ) : null; 52 | 53 | $rules = []; 54 | $rules[] = Type::convertType($column); 55 | $rules[] = ($column->not_null) ? 'required' : 'nullable'; 56 | 57 | if ($column->length) { 58 | $rules[] = 'max:' . $column->length; 59 | } 60 | if ($column->is_unique) { 61 | $rules[] = 'unique'; 62 | } 63 | if ($foreign) { 64 | $rules[] = $foreign; 65 | } 66 | $rules = array_map(function ($item) { 67 | return "'" . $item . "'"; 68 | }, $rules); 69 | return [sprintf("'%s'", $column->name) . ' => [' . implode(', ', $rules) . '],']; 70 | }) 71 | ]; 72 | })->toArray(); 73 | 74 | CreateView::down(); 75 | 76 | $res = '[' . PHP_EOL; 77 | foreach ($response as $tableName => $columns) { 78 | $res .= " '" . $tableName . '\' => [' . PHP_EOL; 79 | foreach ($columns as $column) { 80 | $res .= ' ' . $column[0] . PHP_EOL; 81 | } 82 | $res .= ' ],' . PHP_EOL; 83 | } 84 | $res .= ']'; 85 | 86 | File::put( 87 | config_path('rules.php'), 88 | sprintf("mapWithKeys(function (TableInterface $table) { 42 | return [ 43 | $table->name => $table->columns 44 | ->mapWithKeys(static function (ColumnInterface $column) { 45 | return [$column->name => $column->comment]; 46 | }) 47 | ]; 48 | })->toArray(); 49 | 50 | $tables = Table::all()->mapWithKeys(function (TableInterface $table) { 51 | return [$table->TABLE_NAME => $table->TABLE_COMMENT]; 52 | })->toArray(); 53 | 54 | CreateView::down(); 55 | 56 | $locale = \App::getLocale(); 57 | $dir = \App::langPath($locale); 58 | 59 | if (!file_exists($dir) && !mkdir($dir, true) && !is_dir($dir)) { 60 | throw new \RuntimeException(sprintf('Directory "%s" was not created', $dir)); 61 | } 62 | $old = require($dir . '/columns.php'); 63 | $response = array_merge($response, $old); 64 | 65 | File::put( 66 | $dir . '/columns.php', 67 | sprintf("getDelegate()->getStyle($cellRange)->applyFromArray($style); 31 | }); 32 | 33 | /** 34 | * @see https://phpspreadsheet.readthedocs.io/en/latest/topics/recipes/#setting-a-columns-width 35 | */ 36 | ExcelSheet::macro('setAutoSize', function (ExcelSheet $sheet, int $column) { 37 | $sheet->getDelegate()->getColumnDimensionByColumn($column)->setAutoSize(true); 38 | }); 39 | 40 | /** 41 | * @see https://phpspreadsheet.readthedocs.io/en/latest/topics/recipes/#setting-a-columns-width 42 | */ 43 | ExcelSheet::macro('setColWidth', function (ExcelSheet $sheet, int $column, float $width) { 44 | $sheet->getDelegate()->getColumnDimensionByColumn($column)->setWidth($width); 45 | }); 46 | } 47 | } -------------------------------------------------------------------------------- /src/Exports/DdlExport.php: -------------------------------------------------------------------------------- 1 | output = $output; 41 | $this->tables = Table::all(); 42 | } 43 | 44 | /** 45 | * @return \Closure[] 46 | */ 47 | public function registerEvents(): array 48 | { 49 | return [ 50 | BeforeExport::class => function (BeforeExport $event) { 51 | if ($this->output) { 52 | $this->output->writeln('Exporting...'); 53 | } 54 | }, 55 | BeforeWriting::class => function (BeforeWriting $event) { 56 | if ($this->output) { 57 | $this->output->writeln('Writing...'); 58 | } 59 | }, 60 | ]; 61 | } 62 | 63 | /** 64 | * @return array 65 | */ 66 | public function sheets(): array 67 | { 68 | $sheets = []; 69 | 70 | // Table list 71 | $sheets[] = new ListExport($this->tables); 72 | 73 | foreach ($this->tables as $table) { 74 | $sheets[] = new TableExport($table); 75 | } 76 | 77 | return $sheets; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Exports/ListExport.php: -------------------------------------------------------------------------------- 1 | tables = $tables; 35 | } 36 | 37 | /** 38 | * @return \Illuminate\Support\Collection 39 | */ 40 | public function collection() 41 | { 42 | return $this->tables->map(function (TableInterface $table) { 43 | return collect([ 44 | 'name' => $table->name, 45 | 'comment' => $table->comment, 46 | 'model' => ($table->comment) ? sprintf('App\Models\%s', Str::studly($table->name)) : '' 47 | ]); 48 | }); 49 | } 50 | 51 | /** 52 | * @return \Closure[] 53 | */ 54 | public function registerEvents(): array 55 | { 56 | return [ 57 | AfterSheet::class => function (AfterSheet $event) { 58 | $event->sheet->setColWidth(1, 24); 59 | $event->sheet->setColWidth(2, 24); 60 | $event->sheet->setColWidth(3, 24); 61 | } 62 | ]; 63 | } 64 | 65 | /** 66 | * @return string 67 | */ 68 | public function title(): string 69 | { 70 | return config('app.name'); 71 | } 72 | 73 | /** 74 | * @return string[] 75 | */ 76 | public function headings(): array 77 | { 78 | return [ 79 | '物理名', 80 | '論理名', 81 | 'Model' 82 | ]; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/Exports/TableExport.php: -------------------------------------------------------------------------------- 1 | [ 34 | 'borderStyle' => Border::BORDER_THIN, 35 | ], 36 | 'horizontal' => [ 37 | 'borderStyle' => Border::BORDER_THIN 38 | ], 39 | 'vertical' => [ 40 | 'borderStyle' => Border::BORDER_DOTTED 41 | ], 42 | ]; 43 | 44 | /** 45 | * Cell Background-color setting 46 | * @var array 47 | */ 48 | private $fill = [ 49 | 'fillType' => Fill::FILL_SOLID, 50 | 'color' => [ 51 | 'argb' => 'FFD3F9D8' 52 | ], 53 | ]; 54 | 55 | /** 56 | * TableExport constructor. 57 | * @param TableInterface $table 58 | */ 59 | public function __construct(TableInterface $table) 60 | { 61 | static::setMacro(); 62 | $this->table = $table; 63 | } 64 | 65 | /** 66 | * @return View 67 | */ 68 | public function view(): View 69 | { 70 | return view('ddl::table', ['table' => $this->table]); 71 | } 72 | 73 | /** 74 | * @param string $tag 75 | * @param mixed $columns 76 | * @param mixed $indexes 77 | * @param mixed $referencing 78 | * @param mixed $referenced 79 | * @return array 80 | */ 81 | protected function getRanges(string $tag, $columns, $indexes, $referencing, $referenced) 82 | { 83 | switch ($tag) { 84 | case 'th': 85 | return [ 86 | [ 87 | 'start' => ['column' => 1, 'row' => 2], 88 | 'end' => ['column' => 2, 'row' => 6] 89 | ], 90 | [ 91 | 'start' => ['column' => 1, 'row' => 9], 92 | 'end' => ['column' => 7, 'row' => 9] 93 | ], 94 | [ 95 | 'start' => ['column' => 1, 'row' => $columns->count() + 12], 96 | 'end' => ['column' => 7, 'row' => $columns->count() + 12] 97 | ], 98 | [ 99 | 'start' => ['column' => 1, 'row' => $columns->count() + 15 + $indexes->count()], 100 | 'end' => ['column' => 7, 'row' => $columns->count() + 15 + $indexes->count()] 101 | ], 102 | [ 103 | 'start' => ['column' => 1, 'row' => $columns->count() + 18 + $indexes->count() + $referencing->count()], 104 | 'end' => ['column' => 7, 'row' => $columns->count() + 18 + $indexes->count() + $referencing->count()] 105 | ], 106 | ]; 107 | case 'table': 108 | return [ 109 | [ 110 | 'start' => ['column' => 1, 'row' => 2], 111 | 'end' => ['column' => 7, 'row' => 6] 112 | ], 113 | [ 114 | 'start' => ['column' => 1, 'row' => 10], 115 | 'end' => ['column' => 7, 'row' => 9 + $columns->count()] 116 | ], 117 | [ 118 | 'start' => ['column' => 1, 'row' => $columns->count() + 13], 119 | 'end' => ['column' => 7, 'row' => $columns->count() + $indexes->count() + 12] 120 | ], 121 | [ 122 | 'start' => ['column' => 1, 'row' => $columns->count() + $indexes->count() + 16], 123 | 'end' => ['column' => 7, 'row' => $columns->count() + $indexes->count() + $referencing->count() + 15] 124 | ], 125 | [ 126 | 'start' => ['column' => 1, 'row' => $columns->count() + 18 + $indexes->count() + $referencing->count()], 127 | 'end' => ['column' => 7, 'row' => $columns->count() + 18 + $indexes->count() + $referencing->count() + $referenced->count()] 128 | ], 129 | ]; 130 | } 131 | } 132 | 133 | /** 134 | * @return \Closure[] 135 | */ 136 | public function registerEvents(): array 137 | { 138 | return [ 139 | AfterSheet::class => function (AfterSheet $event) { 140 | foreach ($this->getRanges('th', $this->table->columns, $this->table->indexes, $this->table->referencing, $this->table->referenced) as $rangeByColAndRow) { 141 | $event->sheet->styleCells( 142 | $rangeByColAndRow, 143 | [ 144 | 'borders' => $this->border, 145 | 'fill' => $this->fill 146 | ] 147 | ); 148 | } 149 | foreach ($this->getRanges('table', $this->table->columns, $this->table->indexes, $this->table->referencing, $this->table->referenced) as $rangeByColAndRow) { 150 | $event->sheet->styleCells( 151 | $rangeByColAndRow, 152 | [ 153 | 'borders' => $this->border, 154 | ] 155 | ); 156 | } 157 | 158 | $event->sheet->setColWidth(1, 9); 159 | $event->sheet->setColWidth(2, 18); 160 | $event->sheet->setColWidth(3, 18); 161 | $event->sheet->setColWidth(4, 18); 162 | $event->sheet->setColWidth(5, 18); 163 | $event->sheet->setColWidth(6, 18); 164 | $event->sheet->setColWidth(7, 18); 165 | $event->sheet->setColWidth(8, 18); 166 | } 167 | ]; 168 | } 169 | 170 | /** 171 | * @return string 172 | */ 173 | public function title(): string 174 | { 175 | return $this->table->name; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/Facades/CreateView.php: -------------------------------------------------------------------------------- 1 | repository = $repository; 25 | } 26 | 27 | /** 28 | * @return void 29 | */ 30 | public function up() 31 | { 32 | $this->repository->up(); 33 | } 34 | 35 | /** 36 | * @return void 37 | */ 38 | public function down() 39 | { 40 | $this->repository->down(); 41 | } 42 | } -------------------------------------------------------------------------------- /src/Models/Repositories/MysqlColumn.php: -------------------------------------------------------------------------------- 1 | getDatabaseName(); 45 | $builder->where([ 46 | ['table_schema', '=', $databaseName], 47 | ['table_catalog', '=', 'def'] 48 | ]); 49 | }); 50 | } 51 | 52 | /** 53 | * @return Table 54 | */ 55 | public function table(): Table 56 | { 57 | return $this->TABLE_NAME; 58 | } 59 | 60 | /** 61 | * @return boolean 62 | */ 63 | public function getIsPrimaryKeyAttribute(): bool 64 | { 65 | return $this->primaryKey === $this->COLUMN_NAME; 66 | } 67 | 68 | /** 69 | * @return boolean 70 | */ 71 | public function getIsUniqueAttribute(): bool 72 | { 73 | return $this->COLUMN_KEY === 'UNI'; 74 | } 75 | 76 | /** 77 | * @return string 78 | */ 79 | public function getNameAttribute(): string 80 | { 81 | return $this->COLUMN_NAME; 82 | } 83 | 84 | /** 85 | * @return string 86 | */ 87 | public function getTypeAttribute(): string 88 | { 89 | return $this->DATA_TYPE; 90 | } 91 | 92 | /** 93 | * @return integer|null 94 | */ 95 | public function getLengthAttribute(): ?int 96 | { 97 | return $this->CHARACTER_MAXIMUM_LENGTH; 98 | } 99 | 100 | /** 101 | * @return boolean 102 | */ 103 | public function getNullableAttribute(): bool 104 | { 105 | return $this->IS_NULLABLE === 'YES'; 106 | } 107 | 108 | /** 109 | * @return boolean 110 | */ 111 | public function getNotNullAttribute(): bool 112 | { 113 | return $this->IS_NULLABLE === 'NO'; 114 | } 115 | 116 | /** 117 | * @return mixed 118 | */ 119 | public function getDefaultAttribute() 120 | { 121 | return $this->COLUMN_DEFAULT; 122 | } 123 | 124 | /** 125 | * @return string 126 | */ 127 | public function getCommentAttribute(): string 128 | { 129 | return $this->COLUMN_COMMENT; 130 | } 131 | 132 | /** 133 | * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null 134 | */ 135 | public function getForeignAttribute() 136 | { 137 | return MysqlConstraint::query() 138 | ->where([ 139 | ['table_name', '=', $this->TABLE_NAME], 140 | ['referencing_column_name', '=', $this->COLUMN_NAME], 141 | ]) 142 | ->first(); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/Models/Repositories/MysqlConstraint.php: -------------------------------------------------------------------------------- 1 | getDatabaseName(); 31 | $builder->where('table_catalog', '=', $databaseName); 32 | }); 33 | } 34 | } -------------------------------------------------------------------------------- /src/Models/Repositories/MysqlIndex.php: -------------------------------------------------------------------------------- 1 | getAttribute($key); 36 | } 37 | 38 | /** 39 | * @return boolean 40 | */ 41 | public function isPrimary(): bool 42 | { 43 | return $this->CONSTRAINT_NAME === 'PRIMARY'; 44 | } 45 | 46 | /** 47 | * @return boolean 48 | */ 49 | public function isUnique(): bool 50 | { 51 | return Str::is('*_unique', $this->CONSTRAINT_NAME); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Models/Repositories/MysqlManageView.php: -------------------------------------------------------------------------------- 1 | sql = str_replace(':DATABASE_NAME', DB::getDatabaseName(), $sql); 28 | } 29 | 30 | /** 31 | * @return void 32 | */ 33 | public function up() 34 | { 35 | DB::statement('DROP VIEW IF EXISTS constraints'); 36 | DB::statement($this->sql); 37 | } 38 | 39 | /** 40 | * @return void 41 | */ 42 | public function down() 43 | { 44 | DB::statement('DROP VIEW IF EXISTS constraints'); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Models/Repositories/MysqlTable.php: -------------------------------------------------------------------------------- 1 | getDatabaseName(); 40 | $builder->where([ 41 | ['TABLE_SCHEMA', '=', $databaseName], 42 | ['TABLE_CATALOG', '=', 'def'] 43 | ])->where('TABLE_TYPE', 'BASE TABLE'); 44 | }); 45 | } 46 | 47 | /** 48 | * @return string 49 | */ 50 | public function getNameAttribute(): string 51 | { 52 | return $this->TABLE_NAME; 53 | } 54 | 55 | /** 56 | * @return string 57 | */ 58 | public function getCommentAttribute(): string 59 | { 60 | return $this->TABLE_COMMENT; 61 | } 62 | 63 | /** 64 | * @return HasMany 65 | */ 66 | public function columns(): HasMany 67 | { 68 | return $this->hasMany(MysqlColumn::class, 'TABLE_NAME', 'TABLE_NAME') 69 | ->orderBy('ORDINAL_POSITION'); 70 | } 71 | 72 | /** 73 | * @return HasMany 74 | */ 75 | public function indexes(): HasMany 76 | { 77 | return $this->hasMany(MysqlIndex::class, 'TABLE_NAME', 'TABLE_NAME'); 78 | } 79 | 80 | /** 81 | * @return HasMany 82 | */ 83 | public function referencing(): HasMany 84 | { 85 | return $this->hasMany(MysqlConstraint::class, 'table_name', 'TABLE_NAME'); 86 | } 87 | 88 | /** 89 | * @return HasMany 90 | */ 91 | public function referenced(): HasMany 92 | { 93 | return $this->hasMany(MysqlConstraint::class, 'referenced_table_name', 'TABLE_NAME'); 94 | } 95 | } -------------------------------------------------------------------------------- /src/Models/Repositories/MysqlType.php: -------------------------------------------------------------------------------- 1 | [ 19 | 'bigint', 20 | 'mediumint', 21 | 'smallint', 22 | 'tinyint', 23 | 'int', 24 | 'year', 25 | ], 26 | 'numeric' => [ 27 | 'numeric', 28 | 'decimal', 29 | 'double', 30 | ], 31 | 'string' => [ 32 | 'varchar', 33 | 'char', 34 | 'text', 35 | 'longtext', 36 | ], 37 | 'boolean' => [ 38 | 'bool', 39 | ], 40 | 'date' => [ 41 | 'time', 42 | 'date', 43 | 'datetime', 44 | 'timestamp', 45 | ], 46 | 'json' => [ 47 | 'json', 48 | ], 49 | ]; 50 | 51 | /** 52 | * @param ColumnInterface $column 53 | * @return string 54 | * @throws \Exception 55 | */ 56 | public function convertType(ColumnInterface $column): string 57 | { 58 | foreach ($this->types as $index => $types) { 59 | if (in_array($column->type, $types, true)) { 60 | return $index; 61 | } 62 | } 63 | throw new \Exception('Type not found!: ' . $column->type); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Models/Repositories/PostgresqlColumn.php: -------------------------------------------------------------------------------- 1 | getDatabaseName(); 59 | $builder->where([ 60 | ['table_schema', '=', 'public'], 61 | ['table_catalog', '=', $databaseName] 62 | ]); 63 | }); 64 | } 65 | 66 | /** 67 | * @return Table 68 | */ 69 | public function table(): Table 70 | { 71 | return $this->table_name; 72 | } 73 | 74 | /** 75 | * @return boolean 76 | */ 77 | public function getIsPrimaryKeyAttribute(): bool 78 | { 79 | return $this->primaryKey === $this->column_name; 80 | } 81 | 82 | /** 83 | * @return boolean 84 | */ 85 | public function getIsUniqueAttribute(): bool 86 | { 87 | return false; 88 | } 89 | 90 | /** 91 | * @return string 92 | */ 93 | public function getNameAttribute(): string 94 | { 95 | return $this->column_name; 96 | } 97 | 98 | /** 99 | * @return string 100 | */ 101 | public function getTypeAttribute(): string 102 | { 103 | return $this->udt_name; 104 | } 105 | 106 | /** 107 | * @return integer|null 108 | */ 109 | public function getLengthAttribute(): ?int 110 | { 111 | return $this->character_maximum_length; 112 | } 113 | 114 | /** 115 | * @return boolean 116 | */ 117 | public function getNullableAttribute(): bool 118 | { 119 | return $this->is_nullable === 'YES'; 120 | } 121 | 122 | /** 123 | * @return boolean 124 | */ 125 | public function getNotNullAttribute(): bool 126 | { 127 | return $this->is_nullable === 'NO'; 128 | } 129 | 130 | /** 131 | * @return mixed 132 | */ 133 | public function getDefaultAttribute() 134 | { 135 | return $this->column_default; 136 | } 137 | 138 | /** 139 | * @return string 140 | */ 141 | public function getCommentAttribute(): string 142 | { 143 | $row = DB::table('pg_description') 144 | ->join('pg_stat_all_tables', 'pg_stat_all_tables.relid', '=', 'pg_description.objoid') 145 | ->join('pg_attribute', 'pg_attribute.attrelid', '=', 'pg_description.objoid') 146 | ->whereColumn('pg_description.objoid', 'pg_attribute.attrelid') 147 | ->whereColumn('pg_description.objsubid', 'pg_attribute.attnum') 148 | ->where('pg_stat_all_tables.schemaname', 'public') 149 | ->where('pg_stat_all_tables.relname', $this->table_name) 150 | ->where('pg_attribute.attname', $this->column_name) 151 | ->first('description'); 152 | 153 | return $row->description ?? ''; 154 | } 155 | 156 | /** 157 | * @return Builder|Model|object|null 158 | */ 159 | public function getForeignAttribute() 160 | { 161 | return PostgresqlConstraint::query() 162 | ->where([ 163 | ['table_catalog', '=', $this->table_catalog], 164 | ['table_name', '=', $this->table_name], 165 | ['referencing_column_name', '=', $this->column_name], 166 | ]) 167 | ->first(); 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/Models/Repositories/PostgresqlConstraint.php: -------------------------------------------------------------------------------- 1 | join('information_schema.key_column_usage', function (JoinClause $join) { 28 | $join->on('table_constraints.constraint_catalog', '=', 'key_column_usage.constraint_catalog') 29 | ->whereColumn('table_constraints.constraint_schema', '=', 'key_column_usage.constraint_schema') 30 | ->whereColumn('table_constraints.constraint_name', '=', 'key_column_usage.constraint_name'); 31 | }); 32 | }); 33 | } 34 | 35 | /** 36 | * @return boolean 37 | */ 38 | public function isPrimary(): bool 39 | { 40 | return $this->constraint_type === 'PRIMARY KEY'; 41 | } 42 | 43 | /** 44 | * @return boolean 45 | */ 46 | public function isUnique(): bool 47 | { 48 | return $this->constraint_type === 'UNIQUE'; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Models/Repositories/PostgresqlManageView.php: -------------------------------------------------------------------------------- 1 | sql = File::get(__DIR__ . '/../../sql/psql_create_view.sql'); 27 | } 28 | 29 | /** 30 | * @return void 31 | */ 32 | public function up() 33 | { 34 | DB::statement('DROP VIEW IF EXISTS constraints'); 35 | DB::statement($this->sql); 36 | } 37 | 38 | /** 39 | * @return void 40 | */ 41 | public function down() 42 | { 43 | DB::statement('DROP VIEW IF EXISTS constraints'); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Models/Repositories/PostgresqlTable.php: -------------------------------------------------------------------------------- 1 | getName(); 44 | $databaseName = $connection->getDatabaseName(); 45 | 46 | $builder->when($db === 'pgsql', function (Builder $builder) use ($databaseName) { 47 | $builder->where([ 48 | ['table_schema', '=', 'public'], 49 | ['table_catalog', '=', $databaseName] 50 | ]); 51 | })->when($db === 'mysql', function (Builder $builder) use ($databaseName) { 52 | $builder->where([ 53 | ['table_schema', '=', $databaseName], 54 | ['table_catalog', '=', 'def'] 55 | ]); 56 | })->where('table_type', 'BASE TABLE'); 57 | }); 58 | } 59 | 60 | /** 61 | * @return string 62 | */ 63 | public function getNameAttribute(): string 64 | { 65 | return $this->table_name; 66 | } 67 | 68 | /** 69 | * @return string 70 | */ 71 | public function getCommentAttribute(): string 72 | { 73 | $row = DB::table('pg_stat_user_tables') 74 | ->join('pg_description', 'pg_description.objoid', '=', 'pg_stat_user_tables.relid') 75 | ->where([ 76 | ['pg_stat_user_tables.relname', '=', $this->table_name], 77 | ['pg_description.objsubid', '=', 0] 78 | ]) 79 | ->first('description'); 80 | 81 | return $row->description ?? ''; 82 | } 83 | 84 | /** 85 | * @return HasMany 86 | */ 87 | public function columns(): HasMany 88 | { 89 | return $this->hasMany(PostgresqlColumn::class, 'table_name', 'table_name') 90 | ->orderBy('ordinal_position', 'asc'); 91 | } 92 | 93 | /** 94 | * @return HasMany 95 | */ 96 | public function indexes(): HasMany 97 | { 98 | return $this->hasMany(PostgresqlIndex::class, 'table_name', 'table_name'); 99 | } 100 | 101 | /** 102 | * @return HasMany 103 | */ 104 | public function referencing(): HasMany 105 | { 106 | return $this->hasMany(PostgresqlConstraint::class, 'table_name', 'table_name'); 107 | } 108 | 109 | /** 110 | * @return HasMany 111 | */ 112 | public function referenced(): HasMany 113 | { 114 | return $this->hasMany(PostgresqlConstraint::class, 'referenced_table_name', 'table_name'); 115 | } 116 | } -------------------------------------------------------------------------------- /src/Models/Repositories/PostgresqlType.php: -------------------------------------------------------------------------------- 1 | [ 19 | 'int2', 20 | 'int4', 21 | 'int8', 22 | ], 23 | 'numeric' => [ 24 | 'numeric', 25 | ], 26 | 'string' => [ 27 | 'varchar', 28 | 'bpchar', 29 | 'text', 30 | ], 31 | 'boolean' => [ 32 | 'bool', 33 | ], 34 | 'date' => [ 35 | 'time', 36 | 'date', 37 | 'timestamp', 38 | ], 39 | 'float' => [ 40 | 'float4', 41 | 'float8', 42 | ] 43 | ]; 44 | 45 | /** 46 | * @param ColumnInterface $column 47 | * @return string 48 | * @throws \Exception 49 | */ 50 | public function convertType(ColumnInterface $column): string 51 | { 52 | foreach ($this->types as $index => $types) { 53 | if (in_array($column->type, $types, true)) { 54 | return $index; 55 | } 56 | } 57 | throw new \Exception('Type not found!: ' . $column->type); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Models/Table.php: -------------------------------------------------------------------------------- 1 | repository = $repository; 26 | } 27 | 28 | /** 29 | * @return Collection 30 | */ 31 | public function all(): Collection 32 | { 33 | return $this->repository->with(['columns', 'referencing', 'referenced', 'indexes'])->orderBy('table_name')->get(); 34 | } 35 | 36 | /** 37 | * @param mixed $columns 38 | * @return mixed 39 | */ 40 | public function get($columns) 41 | { 42 | return $this->repository->with(['columns', 'referencing', 'referenced', 'indexes'])->get($columns); 43 | } 44 | 45 | /** 46 | * テーブル名を取得する 47 | * 48 | * @return string 49 | */ 50 | public function name(): string 51 | { 52 | return $this->repository->name; 53 | } 54 | 55 | /** 56 | * テーブルコメントを取得する 57 | * 58 | * @return string 59 | */ 60 | public function comment(): string 61 | { 62 | return $this->repository->comment; 63 | } 64 | } -------------------------------------------------------------------------------- /src/Models/Type.php: -------------------------------------------------------------------------------- 1 | type = $type; 26 | } 27 | 28 | /** 29 | * @param ColumnInterface $column 30 | * @return string 31 | */ 32 | public function convertType(ColumnInterface $column): string 33 | { 34 | return $this->type->convertType($column); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Providers/ServiceProvider.php: -------------------------------------------------------------------------------- 1 | registerCommands(); 32 | 33 | $tableRepository = null; 34 | $constraintRepository = null; 35 | $typeRepository = null; 36 | 37 | $connection = Schema::getConnection(); 38 | if ($connection->getDriverName() === 'pgsql') { 39 | $tableRepository = new PostgresqlTable(); 40 | $constraintRepository = new PostgresqlManageView(); 41 | $typeRepository = new PostgresqlType(); 42 | } elseif ($connection->getDriverName() === 'mysql') { 43 | $tableRepository = new MysqlTable(); 44 | $constraintRepository = new MysqlManageView(); 45 | $typeRepository = new MysqlType(); 46 | } 47 | 48 | $this->app->singleton('shibuyakosuke.table', function () use ($tableRepository) { 49 | return new Table($tableRepository); 50 | }); 51 | 52 | $this->app->singleton('shibuyakosuke.constraints', function () use ($constraintRepository) { 53 | return new CreateView($constraintRepository); 54 | }); 55 | 56 | $this->app->singleton('shibuyakosuke.types', function () use ($typeRepository) { 57 | return new Type($typeRepository); 58 | }); 59 | 60 | $this->loadTranslationsFrom(__DIR__ . '/../../translations', 'ddl'); 61 | 62 | $this->loadViewsFrom(__DIR__ . '/../../views', 'ddl'); 63 | 64 | $this->publishes([ 65 | __DIR__ . '/../../translations' => resource_path('lang/vendor/ddl'), 66 | ]); 67 | } 68 | 69 | /** 70 | * @return void 71 | */ 72 | protected function registerCommands(): void 73 | { 74 | $this->app->singleton('command.shibuyakosuke.db.utilities', static function ($app) { 75 | return new DbUtilitiesCommand(); 76 | }); 77 | $this->app->singleton('command.shibuyakosuke.db.translation', static function ($app) { 78 | return new TransExportCommend(); 79 | }); 80 | $this->app->singleton('command.shibuyakosuke.db.rules', static function ($app) { 81 | return new RuleExportCommend(); 82 | }); 83 | 84 | $this->commands([ 85 | 'command.shibuyakosuke.db.utilities', 86 | 'command.shibuyakosuke.db.translation', 87 | 'command.shibuyakosuke.db.rules', 88 | ]); 89 | } 90 | 91 | /** 92 | * @return array 93 | */ 94 | public function provides(): array 95 | { 96 | return [ 97 | 'command.shibuyakosuke.db.utilities', 98 | 'command.shibuyakosuke.db.translation', 99 | 'command.shibuyakosuke.db.rules', 100 | ]; 101 | } 102 | } -------------------------------------------------------------------------------- /src/sql/mysql_create_view.sql: -------------------------------------------------------------------------------- 1 | CREATE VIEW `constraints` AS 2 | SELECT usg.table_schema as table_catalog, 3 | usg.table_name as table_name, 4 | usg.column_name as referencing_column_name, 5 | usg.REFERENCED_TABLE_NAME as referenced_table_name, 6 | usg.ORDINAL_POSITION as ordinal_position, 7 | usg.REFERENCED_COLUMN_NAME as referenced_column_name, 8 | cst.constraint_name as constraint_name 9 | FROM information_schema.key_column_usage usg 10 | LEFT JOIN information_schema.table_constraints cst 11 | ON usg.table_schema = cst.table_schema 12 | AND usg.constraint_name = cst.constraint_name 13 | WHERE cst.constraint_type = 'FOREIGN KEY' 14 | and usg.table_schema = ':DATABASE_NAME' -------------------------------------------------------------------------------- /src/sql/psql_create_view.sql: -------------------------------------------------------------------------------- 1 | CREATE VIEW "constraints" AS 2 | SELECT table_constraints.table_catalog 3 | , table_constraints.table_name 4 | , kcu.column_name AS "referencing_column_name" 5 | , ref_table_constraints.table_name AS "referenced_table_name" 6 | , ref_ccu.column_name AS "referenced_column_name" 7 | , kcu.ordinal_position 8 | , table_constraints.constraint_name 9 | FROM information_schema.table_constraints table_constraints 10 | INNER JOIN information_schema.key_column_usage kcu 11 | ON table_constraints.constraint_catalog = kcu.constraint_catalog 12 | AND table_constraints.constraint_schema = kcu.constraint_schema 13 | AND table_constraints.constraint_name = kcu.constraint_name 14 | INNER JOIN information_schema.referential_constraints ref_con 15 | ON table_constraints.constraint_catalog = ref_con.constraint_catalog 16 | AND table_constraints.constraint_schema = ref_con.constraint_schema 17 | AND table_constraints.constraint_name = ref_con.constraint_name 18 | INNER JOIN information_schema.table_constraints ref_table_constraints 19 | ON ref_con.unique_constraint_catalog = ref_table_constraints.constraint_catalog 20 | AND ref_con.unique_constraint_schema = ref_table_constraints.constraint_schema 21 | AND ref_con.unique_constraint_name = ref_table_constraints.constraint_name 22 | INNER JOIN information_schema.constraint_column_usage ref_ccu 23 | ON ref_table_constraints.constraint_catalog = ref_ccu.constraint_catalog 24 | AND ref_table_constraints.constraint_schema = ref_ccu.constraint_schema 25 | AND ref_table_constraints.constraint_name = ref_ccu.constraint_name 26 | INNER JOIN information_schema.key_column_usage ref_kcu 27 | ON ref_table_constraints.constraint_catalog = ref_kcu.constraint_catalog 28 | AND ref_table_constraints.constraint_schema = ref_kcu.constraint_schema 29 | AND ref_table_constraints.constraint_name = ref_kcu.constraint_name 30 | AND ref_ccu.column_name = ref_kcu.column_name 31 | AND kcu.ordinal_position = ref_kcu.ordinal_position 32 | ORDER BY table_constraints.table_catalog 33 | , table_constraints.table_name 34 | , table_constraints.constraint_name 35 | , kcu.ordinal_position; -------------------------------------------------------------------------------- /translations/en/ddl.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'title' => 'Tables', 6 | 'app_name' => 'App name', 7 | 'sub_system' => 'SUB SYSTEM', 8 | 'creator' => 'Created by', 9 | 'created_at' => 'Created at', 10 | 'updated_at' => 'Updated at', 11 | 'schema_name' => 'Schema name', 12 | 'logical_name' => 'Logical name', 13 | 'physical_name' => 'Physical name', 14 | 'rdbms' => 'RDBMS', 15 | ], 16 | 'columns' => [ 17 | 'title' => 'Columns', 18 | 'iteration' => 'No.', 19 | 'comment' => 'Logical name', 20 | 'name' => 'Physical name', 21 | 'type' => 'Type', 22 | 'not_null' => 'Not Null', 23 | 'default' => 'Default', 24 | 'extra' => 'Extra', 25 | ], 26 | 'indexes' => [ 27 | 'title' => 'Indexes', 28 | 'iteration' => 'No.', 29 | 'constraint_name' => 'Name', 30 | 'column_name' => 'Columns', 31 | 'primary' => 'Primary key', 32 | 'unique' => 'Unique', 33 | 'extra' => 'Extra', 34 | ], 35 | 'referencing' => [ 36 | 'title' => 'Referencing', 37 | 'iteration' => 'No.', 38 | 'constraint_name' => 'Name', 39 | 'referencing_column_name' => 'Columns', 40 | 'referenced_table_name' => 'Referenced table', 41 | 'referenced_column_name' => 'Referenced columns', 42 | ], 43 | 'referenced' => [ 44 | 'title' => 'Referenced', 45 | 'iteration' => 'No.', 46 | 'constraint_name' => 'Name', 47 | 'referenced_column_name' => 'Referenced column', 48 | 'table_name' => 'Referencing table', 49 | 'referencing_column_name' => 'Referencing column', 50 | ], 51 | ]; -------------------------------------------------------------------------------- /translations/ja/ddl.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'title' => 'テーブル情報', 6 | 'app_name' => 'システム名', 7 | 'sub_system' => 'サブシステム名', 8 | 'creator' => '作成者', 9 | 'created_at' => '作成日', 10 | 'updated_at' => '更新日', 11 | 'schema_name' => 'スキーマ名', 12 | 'logical_name' => '論理テーブル名', 13 | 'physical_name' => '物理テーブル名', 14 | 'rdbms' => 'RDBMS', 15 | ], 16 | 'columns' => [ 17 | 'title' => 'カラム情報', 18 | 'iteration' => 'No.', 19 | 'comment' => '論理名', 20 | 'name' => '物理名', 21 | 'type' => 'データ型', 22 | 'not_null' => 'Not Null', 23 | 'default' => 'デフォルト', 24 | 'extra' => '備考', 25 | ], 26 | 'indexes' => [ 27 | 'title' => 'インデックス情報', 28 | 'iteration' => 'No.', 29 | 'constraint_name' => 'インデックス情報', 30 | 'column_name' => 'カラムリスト', 31 | 'primary' => '主キー', 32 | 'unique' => 'ユニーク', 33 | 'extra' => '備考', 34 | ], 35 | 'referencing' => [ 36 | 'title' => '外部キー情報', 37 | 'iteration' => 'No.', 38 | 'constraint_name' => 'インデックス情報', 39 | 'referencing_column_name' => 'カラムリスト', 40 | 'referenced_table_name' => '参照先テーブル名', 41 | 'referenced_column_name' => '参照先カラムリスト', 42 | ], 43 | 'referenced' => [ 44 | 'title' => '外部キー情報(PK側)', 45 | 'iteration' => 'No.', 46 | 'constraint_name' => 'インデックス情報', 47 | 'referenced_column_name' => 'カラムリスト', 48 | 'table_name' => '参照元テーブル名', 49 | 'referencing_column_name' => '参照元カラムリスト', 50 | ], 51 | ]; -------------------------------------------------------------------------------- /views/table.blade.php: -------------------------------------------------------------------------------- 1 |
2 | 3 |

{{ __('ddl::ddl.table.title') }}

4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
{{ __('ddl::ddl.table.app_name') }}{{ config('app.name') }}{{ __('ddl::ddl.table.creator') }}
{{ __('ddl::ddl.table.sub_system') }}{{ __('ddl::ddl.table.created_at') }}{{ today() }}
{{ __('ddl::ddl.table.schema_name') }}{{ $table->table_schema }}{{ __('ddl::ddl.table.updated_at') }}
{{ __('ddl::ddl.table.logical_name') }}{{ $table->comment }}{{ __('ddl::ddl.table.rdbms') }}
{{ __('ddl::ddl.table.physical_name') }}{{ $table->name }}
39 | 40 |
41 | 42 |
43 | 44 |

{{ __('ddl::ddl.columns.title') }}

45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | @foreach($table->columns as $column) 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | @endforeach 70 | 71 |
{{ __('ddl::ddl.columns.iteration') }}{{ __('ddl::ddl.columns.comment') }}{{ __('ddl::ddl.columns.name') }}{{ __('ddl::ddl.columns.type') }}{{ __('ddl::ddl.columns.not_null') }}{{ __('ddl::ddl.columns.default') }}{{ __('ddl::ddl.columns.extra') }}
{{ $loop->iteration }}{{ $column->comment }}{{ $column->name }}{{ $column->type }}{{ $column->not_null ? 'Yes' : '' }}{{ $column->default }}
72 | 73 |
74 | 75 |
76 | 77 |

{{ __('ddl::ddl.indexes.title') }}

78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | @foreach($table->indexes as $index) 92 | 93 | 94 | 95 | 98 | 101 | 104 | 105 | 106 | @endforeach 107 | 108 |
{{ __('ddl::ddl.indexes.iteration') }}{{ __('ddl::ddl.indexes.constraint_name') }}{{ __('ddl::ddl.indexes.column_name') }}{{ __('ddl::ddl.indexes.primary') }}{{ __('ddl::ddl.indexes.unique') }}{{ __('ddl::ddl.indexes.extra') }}
{{ $loop->iteration }}{{ $index->constraint_name }} 96 | {{ $index->column_name }} 97 | 99 | @if($index->isPrimary()) Yes @endif 100 | 102 | @if($index->isUnique()) Yes @endif 103 |
109 | 110 |
111 | 112 |
113 | 114 |

{{ __('ddl::ddl.referencing.title') }}

115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | @foreach($table->referencing as $constraint) 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | @endforeach 136 | 137 |
{{ __('ddl::ddl.referencing.iteration') }}{{ __('ddl::ddl.referencing.constraint_name') }}{{ __('ddl::ddl.referencing.referencing_column_name') }}{{ __('ddl::ddl.referencing.referenced_table_name') }}{{ __('ddl::ddl.referencing.referenced_column_name') }}
{{ $loop->iteration }}{{ $constraint->constraint_name }}{{ $constraint->referencing_column_name }}{{ $constraint->referenced_table_name }}{{ $constraint->referenced_column_name }}
138 | 139 |
140 | 141 |
142 | 143 |

{{ __('ddl::ddl.referenced.title') }}

144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | @foreach($table->referenced as $constraint) 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | @endforeach 165 | 166 |
{{ __('ddl::ddl.referenced.iteration') }}{{ __('ddl::ddl.referenced.constraint_name') }}{{ __('ddl::ddl.referenced.referenced_column_name') }}{{ __('ddl::ddl.referenced.table_name') }}{{ __('ddl::ddl.referenced.referencing_column_name') }}
{{ $loop->iteration }}{{ $constraint->constraint_name }}{{ $constraint->referenced_column_name }}{{ $constraint->table_name }}{{ $constraint->referencing_column_name }}
167 | 168 |
--------------------------------------------------------------------------------