代码之家  ›  专栏  ›  技术社区  ›  user979331

从模型生成数据库

  •  -1
  • user979331  · 技术社区  · 6 年前

    我正在使用laravel的一个现有项目,这个现有项目已经有了模型,下面是一个示例:

    <?php
    
    /**
     * Created by Reliese Model.
     * Date: Fri, 20 Apr 2018 08:56:36 +0000.
     */
    
    namespace App\Models;
    
    use Reliese\Database\Eloquent\Model as Eloquent;
    
    /**
     * Class PdTcountry
     * 
     * @property int $pkcountry
     * @property string $country_code
     * @property string $country_name
     * @property string $country_localName
     * @property string $country_webCode
     * @property string $country_region
     * @property string $country_continent
     * @property float $country_latitude
     * @property float $country_longitude
     * @property string $country_surfaceArea
     * @property string $country_population
     * @property string $country_postcodeexpression
     * @property \Carbon\Carbon $create_at
     * @property \Carbon\Carbon $update_at
     * 
     * @property \Illuminate\Database\Eloquent\Collection $pd_tregions
     *
     * @package App\Models
     */
    class PdTcountry extends Eloquent
    {
        protected $table = 'pd_tcountry';
        protected $primaryKey = 'pkcountry';
        public $timestamps = false;
    
        protected $casts = [
            'country_latitude' => 'float',
            'country_longitude' => 'float'
        ];
    
        protected $dates = [
            'create_at',
            'update_at'
        ];
    
        protected $fillable = [
            'country_code',
            'country_name',
            'country_localName',
            'country_webCode',
            'country_region',
            'country_continent',
            'country_latitude',
            'country_longitude',
            'country_surfaceArea',
            'country_population',
            'country_postcodeexpression',
            'create_at',
            'update_at'
        ];
    
        public function pd_tregions()
        {
            return $this->hasMany(\App\Models\PdTregion::class, 'fkcountry');
        }
    }
    

    我的问题是,有了这个模型,是否可以通过php Artisan从模型创建一个数据库表?如果有一个php Artisan命令来为我的所有模型执行它,那将是超级的。

    在我的数据库文件夹里有这些,但我不知道它们是做什么的。

    enter image description here

    5 回复  |  直到 6 年前
        1
  •  4
  •   JPark    6 年前

    如果您希望自动生成这些表,那么不,laravel并没有办法做到这一点。理论上,您可以编写自己的命令来为每个模型生成迁移文件,但无论如何,它仍然需要您提供所有的列名、数据类型等。看看拉维尔的 make:migration 例如命令。它只使用存根文件并在生成时替换关键字( vendor/laravel/framework/src/Illuminate/Database/Migrations/MigrationCreator.php )中。如果您有大量需要数据库表的模型,那么这可能是一个很好的方法。

    如果不是,那么最好使用标准命令生成迁移,并将 --create 标签。之后,您只需在模型中定义表(或使用命名约定使其自动查找表,请参见: https://laravel.com/docs/5.6/eloquent#defining-models 有关命名约定的更多信息)。

    例子:

    php artisan make:migration create_my_model_table --create=my_model_table_name
    

    如果不使用命名约定,请将表名添加到模型中:

    class PdTcountry extends Eloquent {
    
        protected $table = "my_model_table_name"
    
        ...
    }
    
        2
  •  2
  •   Erik Berkun-Drevnig    6 年前

    有路经过吗 php artisan 从模型创建数据库表?

    听起来你想要的是“代码优先设计”。这在微软的实体框架中是支持的,但是在laravel中,工作方式有些不同。在c中,使用实体框架可以创建属性(基本上是getter方法)来对应每个数据库列。以雄辩的口才 ORM 库)它使用php动态生成这些 magic methods ,php变量也像c那样缺少类型。因此,无法按照所需的方式基于代码填充数据库。您在问题中发布的文档注释看起来像是使用 laravel-ide-helper 包裹。

    或者一些数据库客户端 Sequel Pro 有一个插件将现有的数据库模式导出到LaaFLE迁移中,在过去我发现它非常快速和有用,并且可能是您要找的工作流中最接近的东西。祝你好运!

    Exporting a database schema as a Laravel migration

    我的数据库文件夹中有(一组迁移文件),但我不知道它们是做什么的。

    你应该看看相关的 documentation on the Laravel website .迁移已经生成,因此需要配置本地数据库并运行 migrate 命令。这将创建应用程序所需的表和列。在对架构进行更改时,应添加更多迁移并重新运行 迁移 命令。

    php artisan migrate
    
        3
  •  0
  •   Niellles    6 年前

    正如其他人所指出的:这不是拉勒维尔,或者确切地说是雄辩的形式,是如何工作的。通常,首先创建一个表(即进行迁移),然后创建模型。坚持拉氏法可以节省很多时间 model conventions 是的。

    但是,您已经有一个或多个模型似乎缺少迁移。我建议您简单地为这些模型添加迁移。不幸的是,如果您有很多模型,特别是当您不遵守表名和其他约定时(例如您的示例模型),这将是一项非常艰巨的工作。

    另一方面,在您的模型中,您已经有了许多将要用于迁移的信息。您可以从doccomments和属性中提取此信息,如 $table 我是说, $primaryKey 我是说, $fillable 等。这可以自动完成。我已经给出了一个远未完成的示例,但至少应该让您从迁移的基础开始。然后,您可以决定手动执行其余部分,或将功能添加到自动流程中。我个人只有当我有很多模特的时候才会做后者。


    例子

    我以你问题中的模型为例。

    如我所说,它还远未完成,我想到了以下补充/改进:

    1. 确定关系并以此为基础建立外键。(看看这个 post 以获得一些灵感。)
    2. 将更多数据类型添加到 switch 是的。

    将以下特征另存为 app/SchemaBuilder.php 以下内容:

    <?php
    
    namespace App;
    
    trait SchemaBuilder
    {
        public function printMigration()
        {
            echo '<pre>';
            echo htmlspecialchars($this->generateMigration());
            echo '</pre>';
        }
    
        public function makeMigrationFile()
        {
            if ($this->migrationFileExists()) {
                die('It appears that a migration for this model already exists. Please check it out.');
            }
            $filename = date('Y_m_t_His') . '_create_' . $this->table . '_table.php';
            if (file_put_contents(database_path('migrations/') . $filename, $this->generateMigration())) {
                return true;
            }
    
            return false;
        }
    
        protected function generateMigration()
        {
            return sprintf($this->getSchemaTemplate(),
                ucfirst($this->table), $this->table,
                implode("\n\t\t\t", $this->generateFieldCreationFunctions()),
                $this->table
            );
        }
    
        protected function getSchemaTemplate()
        {
            $schema = "<?php\n";
            $schema .= "\n";
            $schema .= "use Illuminate\\Support\\Facades\\Schema;\n";
            $schema .= "use Illuminate\\Database\\Schema\\Blueprint;\n";
            $schema .= "use Illuminate\\Database\\Migrations\\Migration;\n";
            $schema .= "\n";
            $schema .= "class Create%sTable extends Migration\n";
            $schema .= "{\n";
            $schema .= "\t/**\n";
            $schema .= "\t* Run the migrations.\n";
            $schema .= "\t*\n";
            $schema .= "\t* @return void\n";
            $schema .= "\t*/\n";
            $schema .= "\tpublic function up()\n";
            $schema .= "\t{\n";
            $schema .= "\t\tSchema::create('%s', function (Blueprint \$table) {\n";
            $schema .= "\t\t\t%s\n"; # Actual database fields will be added here.
            $schema .= "\t\t});\n";
            $schema .= "\t}\n";
            $schema .= "\n";
            $schema .= "\t/**\n";
            $schema .= "\t* Reverse the migrations.\n";
            $schema .= "\t*\n";
            $schema .= "\t* @return void\n";
            $schema .= "\t*/\n";
            $schema .= "\tpublic function down()\n";
            $schema .= "\t{\n";
            $schema .= "\t\tSchema::drop('%s');\n";
            $schema .= "\t}\n";
            $schema .= "}";
    
            return $schema;
        }
    
        protected function generateFieldCreationFunctions()
        {
            $functions = [];
    
            if (isset($this->primaryKey)) {
                $functions[] = "\$table->increments('$this->primaryKey');";
            }
    
            $featuresFromDoc = $this->extractFieldDataFromCommentDoc();
            $functions[] = ""; # Hack our way to an empty line.
            foreach ($this->fillable as $fillableField) {
                if (in_array($fillableField, $this->dates)) { # We'll handle fields in $dates later.
                    continue;
                }
    
                if (!isset($featuresFromDoc[$fillableField])) {
                    $functions[] = "//Manually do something with $fillableField";
                }
    
                switch ($featuresFromDoc[$fillableField]) {
                    case 'string':
                        $functions[] = "\$table->string('$fillableField'); //TODO: check whether varchar is the correct field type.";
                        break;
                    case 'int':
                        $functions[] = "\$table->integer('$fillableField'); //TODO: check whether integer is the correct field type.";
                        break;
                    case 'float':
                        $functions[] = "\$table->float('$fillableField', 12, 10);";
                        break;
                    default:
                        $functions[] = "//Manually do something with $fillableField";
                }
            }
    
            $functions[] = ""; # Empty line.
            foreach ($this->dates as $dateField) {
                $functions[] = "\$table->dateTime('$dateField');";
            }
    
            $functions[] = ""; # Empty line.
            if (!empty($this->timestamps)) {
    
                $functions[] = "\$table->timestamps();";
            }
            return $functions;
        }
    
        protected function extractFieldDataFromCommentDoc()
        {
            $doc_comment = (new \ReflectionClass(get_parent_class($this)))->getDocComment();
    
            preg_match_all('/@property (.+) \$(.+)/', $doc_comment, $matches, PREG_SET_ORDER);
    
            foreach ($matches as $match) {
                $features[$match[2]] = $match[1];
            }
    
            return $features;
        }
    
        protected function migrationFileExists()
        {
            $path = database_path('migrations');
    
            if ($handle = opendir($path)) {
                while (false !== ($file = readdir($handle))) {
                    if (strpos($file, 'create_' . $this->table . '_table') !== false) {
                        return true;
                    }
                }
                closedir($handle);
            }
    
            return false;
        }
    }
    

    创建以下控制器并注册路由,以便您可以访问它:

    <?php
    
    namespace App\Http\Controllers;
    
    use App\PdTcountry;
    use Illuminate\Http\Request;
    
    class TestController extends Controller
    {
        public function index()
        {
            # Specify for which model you'd like to build a migration.
            $buildSchemaFor = 'App\PdTcountry';
    
            eval(sprintf('class MigrationBuilder extends %s{use \App\SchemaBuilder;}', $buildSchemaFor));
    
            if ((new \MigrationBuilder)->makeMigrationFile()) {
                echo 'Migration file successfully created.';
            }
            else {
                echo 'Encountered error while making migration file.';
            }
    
            # Or alternatively, print the migration file to the browser:
    //        (new \MigrationBuilder)->printMigration();
    
    
        }
    }
    
        4
  •  0
  •   Polaris    6 年前

    下面是一个您可以安装的composer包,它可以从您的模型创建数据库表。它叫reliese。

    https://github.com/reliese/laravel

    希望这对你有帮助,这也是你想要的。

        5
  •  -2
  •   Aakash Tushar    6 年前

    跑步 php artisan migrate 在控制台里。这将生成在您的定义中存在的表。 database/migrations 文件夹如问题图片所示。