diff --git a/spec/Migrations/SyntaxBuilderSpec.php b/spec/Migrations/SyntaxBuilderSpec.php index 074fe70..44b3cee 100644 --- a/spec/Migrations/SyntaxBuilderSpec.php +++ b/spec/Migrations/SyntaxBuilderSpec.php @@ -28,6 +28,41 @@ function it_creates_the_php_syntax_for_the_schema() $this->create($schema, ['table' => 'posts', 'action' => 'create'])['down']->shouldBe("Schema::dropIfExists('posts');"); } + function it_doesnt_add_duplicate_id_field() + { + $schema = [ + [ + 'name' => 'id', + 'type' => 'increments', + 'arguments' => [], + 'options' => [], + ], [ + "name" => "email", + "type" => "string", + "arguments" => ["100"], + "options" => [ + "unique" => true, + "nullable" => true, + "default" => '"foo@example.com"' + ] + ] + ]; + + $this->create($schema, ['table' => 'posts', 'action' => 'create'])['up']->shouldBe(getStub()); + } + + function it_doesnt_add_duplicate_timestamp_fields() + { + $schema = [[ + 'name' => 'created_at', + 'type' => 'date', + 'arguments' => [], + 'options' => [], + ]]; + + $this->create($schema, ['table' => 'posts', 'action' => 'create'])['up']->shouldBe(getTimestampStub()); + } + } function getStub() @@ -40,3 +75,13 @@ function getStub() }); EOT; } + +function getTimestampStub() +{ + return <<increments('id'); + \$table->date('created_at'); + }); +EOT; +} diff --git a/src/Migrations/SyntaxBuilder.php b/src/Migrations/SyntaxBuilder.php index 4713e11..a9b06ea 100644 --- a/src/Migrations/SyntaxBuilder.php +++ b/src/Migrations/SyntaxBuilder.php @@ -151,6 +151,14 @@ private function constructSchema($schema, $direction = 'Add') { if (!$schema) return ''; + if (!$this->hasDefinedIdColumn($schema)) { + $schema = $this->addIdColumn($schema); + } + + if (!$this->hasDefinedTimestamps($schema)) { + $schema = $this->addTimestamps($schema); + } + $fields = array_map(function ($field) use ($direction) { $method = "{$direction}Column"; @@ -169,7 +177,7 @@ private function constructSchema($schema, $direction = 'Add') */ private function addColumn($field) { - $syntax = sprintf("\$table->%s('%s')", $field['type'], $field['name']); + $syntax = sprintf("\$table->%s(%s)", $field['type'], empty($field['name']) ? '' : "'$field[name]'"); // If there are arguments for the schema type, like decimal('amount', 5, 2) // then we have to remember to work those in. @@ -196,4 +204,115 @@ private function dropColumn($field) { return sprintf("\$table->dropColumn('%s');", $field['name']); } + + /** + * Check to see if the user has already provided an id field + * + * @param array $schema + * + * @return bool + */ + private function hasDefinedIdColumn(array $schema) + { + foreach ($schema as $definition) { + if ($definition['name'] === 'id') { + return true; + } + } + + return false; + } + + /** + * Check to see if the user has already defined timestamp field(s) + * + * @param array $schema + * + * @return bool + */ + private function hasDefinedTimestamps(array $schema) + { + $created_at = false; + $updated_at = false; + + foreach ($schema as $definition) { + if ($definition['name'] === 'created_at') { + $created_at = true; + } else if ($definition['name'] === 'updated_at') { + $updated_at = true; + } + } + + return ($created_at || $updated_at); + } + + /** + * Adds an ID field to the beginning of the schema definition + * + * @param array $schema + * + * @return array + */ + private function addIdColumn(array $schema) + { + return $this->appendFieldToSchema($schema, 'id', 'increments'); + } + + /** + * Adds the timestamps option to the end of the schema definition + * + * @param array $schema + * + * @return array + */ + private function addTimestamps(array $schema) + { + return $this->prependFieldToSchema($schema, '', 'timestamps'); + } + + /** + * Adds a field to the start of the schema definition + * + * @param array $schema + * @param string $name + * @param string $type + * @param array $arguments + * @param array $options + * + * @return array + */ + private function appendFieldToSchema(array $schema, $name, $type, $arguments = [], $options = []) + { + array_unshift($schema, [ + 'name' => $name, + 'type' => $type, + 'arguments' => $arguments, + 'options' => $options, + ]); + + return $schema; + } + + /** + * Adds a field to the end of the schema definition + * + * @param array $schema + * @param string $name + * @param string $type + * @param array $arguments + * @param array $options + * + * @return array + */ + private function prependFieldToSchema(array $schema, $name, $type, $arguments = [], $options = []) + { + array_push($schema, [ + 'name' => $name, + 'type' => $type, + 'arguments' => $arguments, + 'options' => $options, + ]); + + return $schema; + } } diff --git a/src/stubs/schema-create.stub b/src/stubs/schema-create.stub index e1be930..eb6aea5 100644 --- a/src/stubs/schema-create.stub +++ b/src/stubs/schema-create.stub @@ -1,5 +1,3 @@ Schema::create('{{table}}', function (Blueprint $table) { - $table->increments('id'); {{schema_up}} - $table->timestamps(); }); \ No newline at end of file