diff --git a/src/Generators/MigrationGenerator.php b/src/Generators/MigrationGenerator.php index bce28294..df481e57 100644 --- a/src/Generators/MigrationGenerator.php +++ b/src/Generators/MigrationGenerator.php @@ -15,6 +15,8 @@ class MigrationGenerator implements Generator /** @var \Illuminate\Contracts\Filesystem\Filesystem */ private $files; + private $pivotTables = []; + public function __construct($files) { $this->files = $files; @@ -34,6 +36,26 @@ public function output(array $tree): array $this->files->put($path, $this->populateStub($stub, $model)); $output['created'][] = $path; + + if (!empty($modelPivots = $model->pivotTables())) { + foreach ($modelPivots as $pivotSegments) { + $pivotTable = $this->getPivotTableName($pivotSegments); + if (!isset($this->pivotTables[$pivotTable])) { + $this->pivotTables[$pivotTable] = [ + 'tableName' => $pivotTable, + 'segments' => $pivotSegments + ]; + } + } + } + } + + if (!empty($this->pivotTables)) { + foreach ($this->pivotTables as $pivotTable) { + $path = $this->getPivotTablePath($pivotTable['tableName'], $sequential_timestamp->addSecond()); + $this->files->put($path, $this->populatePivotStub($stub, $pivotTable['segments'])); + $output['created'][] = $path; + } } return $output; @@ -48,6 +70,15 @@ protected function populateStub(string $stub, Model $model) return $stub; } + protected function populatePivotStub(string $stub, array $segments) + { + $stub = str_replace('DummyClass', $this->getPivotClassName($segments), $stub); + $stub = str_replace('DummyTable', $this->getPivotTableName($segments), $stub); + $stub = str_replace('// definition...', $this->buildPivotTableDefinition($segments), $stub); + + return $stub; + } + protected function buildDefinition(Model $model) { $definition = ''; @@ -107,6 +138,18 @@ protected function buildDefinition(Model $model) return trim($definition); } + protected function buildPivotTableDefinition(array $segments, $dataType = 'bigIncrements') + { + $definition = ''; + + foreach ($segments as $segment) { + $column = $segment . '_id'; + $definition .= self::INDENT . '$table->' . $dataType . "('{$column}');" . PHP_EOL; + } + + return trim($definition); + } + protected function getClassName(Model $model) { return 'Create' . Str::studly($model->tableName()) . 'Table'; @@ -117,8 +160,27 @@ protected function getPath(Model $model, Carbon $timestamp) return 'database/migrations/' . $timestamp->format('Y_m_d_His') . '_create_' . $model->tableName() . '_table.php'; } + protected function getPivotTablePath($tableName, Carbon $timestamp) + { + return 'database/migrations/' . $timestamp->format('Y_m_d_His') . '_create_' . $tableName . '_table.php'; + } + protected function isLaravel7orNewer() { return version_compare(App::version(), '7.0.0', '>='); } + + protected function getPivotClassName(array $segments) + { + return 'Create' . Str::studly($this->getPivotTableName($segments)) . 'PivotTable'; + } + + protected function getPivotTableName(array $segments) + { + $segments = array_map(function ($name) { + return Str::snake($name); + }, $segments); + sort($segments); + return strtolower(implode('_', $segments)); + } } diff --git a/src/Generators/ModelGenerator.php b/src/Generators/ModelGenerator.php index 0cf82899..d0250370 100644 --- a/src/Generators/ModelGenerator.php +++ b/src/Generators/ModelGenerator.php @@ -135,7 +135,7 @@ private function buildRelationships(Model $model) $class = Str::studly($class ?? $name); $relationship = sprintf("\$this->%s(%s::class)", $type, '\\' . $model->fullyQualifiedNamespace() . '\\' . $class); - $method_name = $type === 'hasMany' ? Str::plural($name) : $name; + $method_name = $type === 'hasMany' || $type === 'belongsToMany' ? Str::plural($name) : $name; $method = str_replace('DummyName', Str::camel($method_name), $template); $method = str_replace('null', $relationship, $method); $methods .= PHP_EOL . $method; diff --git a/src/Lexers/ModelLexer.php b/src/Lexers/ModelLexer.php index bb6062b1..c5d62dcc 100644 --- a/src/Lexers/ModelLexer.php +++ b/src/Lexers/ModelLexer.php @@ -12,6 +12,7 @@ class ModelLexer implements Lexer 'belongsto' => 'belongsTo', 'hasone' => 'hasOne', 'hasmany' => 'hasMany', + 'belongstomany' => 'belongsToMany' ]; private static $dataTypes = [ diff --git a/src/Models/Model.php b/src/Models/Model.php index 39062e47..c58512c9 100644 --- a/src/Models/Model.php +++ b/src/Models/Model.php @@ -12,6 +12,7 @@ class Model private $softDeletes = false; private $columns = []; private $relationships = []; + private $pivotTables = []; /** * @param $name @@ -132,6 +133,22 @@ public function addRelationship(string $type, string $reference) $this->relationships[$type] = []; } + if ($type === 'belongsToMany') { + $this->addPivotTable($reference); + } + $this->relationships[$type][] = $reference; } + + public function addPivotTable(string $reference) + { + $segments = [$this->name(), strtolower($reference)]; + sort($segments); + $this->pivotTables[] = $segments; + } + + public function pivotTables(): array + { + return $this->pivotTables; + } }