From d524e70be92e5e9acd887f6f95703e23571c79cd Mon Sep 17 00:00:00 2001 From: The Doctor Date: Sat, 27 Jun 2020 13:24:29 +0200 Subject: [PATCH 1/3] Add better support for enums. --- src/Console/GenerateCommand.php | 81 +++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/src/Console/GenerateCommand.php b/src/Console/GenerateCommand.php index 57f814e..dce8306 100644 --- a/src/Console/GenerateCommand.php +++ b/src/Console/GenerateCommand.php @@ -243,7 +243,7 @@ protected function getPropertiesFromTable($model) $name !== $model::UPDATED_AT ) { if (!method_exists($model, 'getDeletedAtColumn') || (method_exists($model, 'getDeletedAtColumn') && $name !== $model->getDeletedAtColumn())) { - $this->setProperty($name, $type, $table); + $this->setProperty($model, $name, $type, $table); } } } @@ -277,7 +277,7 @@ protected function getPropertiesFromMethods($model) if ($pos = stripos($code, $search)) { $relationObj = $model->$method(); if ($relationObj instanceof Relation) { - $this->setProperty($relationObj->getForeignKeyName(), 'factory(' . get_class($relationObj->getRelated()) . '::class)'); + $this->setProperty($model, $relationObj->getForeignKeyName(), 'factory(' . get_class($relationObj->getRelated()) . '::class)'); } } } @@ -289,7 +289,7 @@ protected function getPropertiesFromMethods($model) * @param string $name * @param string|null $type */ - protected function setProperty($name, $type = null, $table = null) + protected function setProperty($model, $name, $type = null, $table = null) { if ($type !== null && Str::startsWith($type, 'factory(')) { $this->properties[$name] = $type; @@ -297,23 +297,6 @@ protected function setProperty($name, $type = null, $table = null) return; } - $fakeableTypes = [ - 'enum' => '$faker->randomElement(' . $this->enumValues($table, $name) . ')', - 'string' => '$faker->word', - 'text' => '$faker->text', - 'date' => '$faker->date()', - 'time' => '$faker->time()', - 'guid' => '$faker->word', - 'datetimetz' => '$faker->dateTime()', - 'datetime' => '$faker->dateTime()', - 'integer' => '$faker->randomNumber()', - 'bigint' => '$faker->randomNumber()', - 'smallint' => '$faker->randomNumber()', - 'decimal' => '$faker->randomFloat()', - 'float' => '$faker->randomFloat()', - 'boolean' => '$faker->boolean' - ]; - $fakeableNames = [ 'city' => '$faker->city', 'company' => '$faker->company', @@ -354,6 +337,31 @@ protected function setProperty($name, $type = null, $table = null) return; } + $enumValues = $this->enumValues($model, $table, $name); + + $fakeableTypes = [ + 'enum' => '$faker->randomElement(' . $enumValues . ')', + 'string' => '$faker->word', + 'text' => '$faker->text', + 'date' => '$faker->date()', + 'time' => '$faker->time()', + 'guid' => '$faker->word', + 'datetimetz' => '$faker->dateTime()', + 'datetime' => '$faker->dateTime()', + 'integer' => '$faker->randomNumber()', + 'bigint' => '$faker->randomNumber()', + 'smallint' => '$faker->randomNumber()', + 'decimal' => '$faker->randomFloat()', + 'float' => '$faker->randomFloat()', + 'boolean' => '$faker->boolean' + ]; + + if ($enumValues !== '[]') { + $this->properties[$name] = $fakeableTypes['enum']; + + return; + } + if (isset($fakeableTypes[$type])) { $this->properties[$name] = $fakeableTypes[$type]; @@ -363,19 +371,42 @@ protected function setProperty($name, $type = null, $table = null) $this->properties[$name] = '$faker->word'; } - public static function enumValues($table, $name) + public function enumValues($model, $table, $name) { if ($table === null) { return "[]"; } - $type = DB::select(DB::raw('SHOW COLUMNS FROM ' . $table . ' WHERE Field = "' . $name . '"'))[0]->Type; + $driver = $model->getConnection()->getDriverName(); + $values = null; + + if ($driver === 'mysql') { + $type = DB::select(DB::raw('SHOW COLUMNS FROM ' . $table . ' WHERE Field = "' . $name . '"'))[0]->Type; - preg_match_all("/'([^']+)'/", $type, $matches); + preg_match_all("/'([^']+)'/", $type, $matches); - $values = isset($matches[1]) ? $matches[1] : array(); + $values = isset($matches[1]) ? $matches[1] : array(); + + return "['" . implode("', '", $values) . "']"; + } else if ($driver === 'pgsql') { + $types = DB::select(DB::raw(" + select matches[1] + from pg_constraint, regexp_matches(consrc, '''(.+?)''', 'g') matches + where contype = 'c' + and conname = '{$table}_{$name}_check' + and conrelid = 'public.{$table}'::regclass; + ")); + + $values = array(); + + foreach ($types as $type){ + $values[] = $type->matches; + } + } - return "['" . implode("', '", $values) . "']"; + return $values + ? "['" . implode("', '", $values) . "']" + : "[]"; } From fee97938f47fc0171bd140c5a8a700320d4ec4d0 Mon Sep 17 00:00:00 2001 From: The Doctor Date: Thu, 3 Sep 2020 18:30:19 +0200 Subject: [PATCH 2/3] Use model connection when selecting model field enum values. --- src/Console/GenerateCommand.php | 34 +++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/Console/GenerateCommand.php b/src/Console/GenerateCommand.php index dce8306..23e8e38 100644 --- a/src/Console/GenerateCommand.php +++ b/src/Console/GenerateCommand.php @@ -381,26 +381,28 @@ public function enumValues($model, $table, $name) $values = null; if ($driver === 'mysql') { - $type = DB::select(DB::raw('SHOW COLUMNS FROM ' . $table . ' WHERE Field = "' . $name . '"'))[0]->Type; + $type = DB::connection($model->getConnectionName()) + ->select(DB::raw('SHOW COLUMNS FROM ' . $table . ' WHERE Field = "' . $name . '"'))[0]->Type; preg_match_all("/'([^']+)'/", $type, $matches); - $values = isset($matches[1]) ? $matches[1] : array(); - - return "['" . implode("', '", $values) . "']"; + $values = isset($matches[1]) ? $matches[1] : null; } else if ($driver === 'pgsql') { - $types = DB::select(DB::raw(" - select matches[1] - from pg_constraint, regexp_matches(consrc, '''(.+?)''', 'g') matches - where contype = 'c' - and conname = '{$table}_{$name}_check' - and conrelid = 'public.{$table}'::regclass; - ")); - - $values = array(); - - foreach ($types as $type){ - $values[] = $type->matches; + $types = DB::connection($model->getConnectionName()) + ->select(DB::raw(" + select matches[1] + from pg_constraint, regexp_matches(consrc, '''(.+?)''', 'g') matches + where contype = 'c' + and conname = '{$table}_{$name}_check' + and conrelid = 'public.{$table}'::regclass; + ")); + + if (count($types)) { + $values = array(); + + foreach ($types as $type){ + $values[] = $type->matches; + } } } From b35b0dc0458443312e2eda0e51a61db80c869641 Mon Sep 17 00:00:00 2001 From: The Doctor Date: Thu, 3 Sep 2020 18:30:32 +0200 Subject: [PATCH 3/3] Fix column type check on PostgreSQL 12+. --- src/Console/GenerateCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Console/GenerateCommand.php b/src/Console/GenerateCommand.php index 23e8e38..d167e8d 100644 --- a/src/Console/GenerateCommand.php +++ b/src/Console/GenerateCommand.php @@ -391,7 +391,7 @@ public function enumValues($model, $table, $name) $types = DB::connection($model->getConnectionName()) ->select(DB::raw(" select matches[1] - from pg_constraint, regexp_matches(consrc, '''(.+?)''', 'g') matches + from pg_constraint, regexp_matches(pg_get_constraintdef(\"oid\"), '''(.+?)''', 'g') matches where contype = 'c' and conname = '{$table}_{$name}_check' and conrelid = 'public.{$table}'::regclass;