laravel 从模型生成数据库

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/51158766/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 17:52:18  来源:igfitidea点击:

laravel generate database from model

phplaravelartisan

提问by user979331

I am using an existing project of Laravel and this existing project already has models, here is an example of one:

我正在使用 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');
    }
}

My question is, with this Model is there away via php artisan to create a database table from the model? If there is a php artisan command to do it for all my models that would be super.

我的问题是,使用此模型是否可以通过 php artisan 从模型创建数据库表?如果有一个 php artisan 命令可以为我的所有模型执行此操作,那就太好了。

In my database folder I have these, but I don't know what they do.

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

enter image description here

在此处输入图片说明

回答by JPark

If you are looking to generate these tables automagically, then no, Laravel doesn't really have a way to do that. In theory, you could write your own command to generate migration files for each of your models, but it will still require you to provide all the column names, data types, etc. anyways. Take a look at Laravel's make:migrationcommand for instance. It just uses stub files and replaces key words when generating (vendor/laravel/framework/src/Illuminate/Database/Migrations/MigrationCreator.php). If you have a ton of models that need database tables, then maybe this would be a good approach for you to dive into.

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

If not, however, you're probably best off generating a migration using the standard command and just supply it with the --createtag. Afterwards, you would just have to define your table in your model (or use the naming convention so it finds it automatically, see: https://laravel.com/docs/5.6/eloquent#defining-modelsfor more info on the naming conventions).

但是,如果没有,您可能最好使用标准命令生成迁移,并只为它提供--create标签。之后,您只需要在模型中定义表(或使用命名约定以便它自动找到它,请参阅:https: //laravel.com/docs/5.6/eloquent#defining-models了解有关命名的更多信息约定)。

Example:

例子:

php artisan make:migration create_my_model_table --create=my_model_table_name

If you don't use the naming convention, add your table name to your model:

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

class PdTcountry extends Eloquent {

    protected $table = "my_model_table_name"

    ...
}

回答by Erik Berkun-Drevnig

Is there a way via php artisanto create a database table from the model?

有没有办法通过php artisan从模型创建数据库表?

It sounds like what you want is "Code-First Design". This is supported in Microsoft's Entity Framework however in Laravel the way things work is somewhat different. In C# with Entity framework one would create properties (basically getter methods) to correspond with each database column. With Eloquent (Laravel's ORMlibrary) it generates these dynamically using PHP magic methods, PHP variables also lack types in the way that C# does. Because of this there is no way to populate the database based on the code in the way you want. The doc comments you posted in your question look like they were generated the other way around from database to code, using the laravel-ide-helperpackage.

听起来您想要的是“代码优先设计”。这在 Microsoft 的实体框架中得到支持,但是在 Laravel 中,事情的工作方式有些不同。在带有实体框架的 C# 中,可以创建与每个数据库列对应的属性(基本上是 getter 方法)。使用 Eloquent(Laravel 的ORM库),它使用 PHP魔术方法动态生成这些,PHP 变量也缺少 C# 那样的类型。因此,无法以您想要的方式根据代码填充数据库。您在问题中发布的文档评论看起来像是使用laravel-ide-helper包从数据库到代码以相反的方式生成的。

Alternatively some database clients like Sequel Prohave a plugin to export the existing database schema into a Laravel migration which I have found very quick and helpful in the past and might be the closest thing you can get to the workflow you're looking for. Good luck!

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

Exporting a database schema as a Laravel migration

将数据库模式导出为 Laravel 迁移

I have (a set of migration files) in my database folder, but I don't know what they do.

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

You should check out the relevant documentation on the Laravel website. The migrations have already been generated so you need to configure a local database and run the migratecommand. This will create the tables and columns necessary for your application. As you make changes to the schema you should add more migrations and rerun the migratecommand.

您应该查看Laravel 网站上的相关文档。迁移已经生成,因此您需要配置本地数据库并运行migrate命令。这将创建应用程序所需的表和列。当您更改架构时,您应该添加更多迁移并重新运行migrate命令。

php artisan migrate

回答by Niellles

As others have pointed out: this is not how Laravel, or the Eloquent ORM to be exact, works. Normally you'd first create a table (i.e. make a migration) and then create your model. A lot of time can be saved by adhering to Laravels model conventions.

正如其他人指出的那样:这不是 Laravel,或者确切地说是 Eloquent ORM 的工作方式。通常,您首先创建一个表(即进行迁移),然后创建您的模型。遵守 Laravel模型约定可以节省大量时间。

However, you already have one or more models that seem to be missing a migration. I'd advice you to simply add migrations for these models. Unfortunately this will be a lot of work if you have a lot of models and, especially (as is the case with your example model) when you didn't adhere to the table name, and other, conventions.

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

On the other hand, you already have a lot of the information that's going to go into your migration, available in your Model. You could extract this information from the DocComments and properties like $table, $primaryKey, $fillable, etc. This could be done automatically. I've put together an example that's far from complete, but should at least get you started with the base of your migration. You can then decide to do the remaining parts manually or add functionality to the automatic process. I'd personally only do the latter if I had a lot of models.

另一方面,您已经拥有许多将要迁移到您的模型中的信息。你可以从中提取DocComments和这类似的房屋信息$table$primaryKey$fillable等这可以自动完成。我整理了一个远未完成的示例,但至少应该让您开始了解迁移的基础。然后,您可以决定手动完成其余部分或向自动流程添加功能。如果我有很多模型,我个人只会做后者。



Example

例子

I've based this example of the model included in your question.

我已经基于您的问题中包含的模型的这个示例。

As I said; it's far from complete, the following additions/improvements come to mind:

就像我说的; 它远未完成,想到了以下添加/改进:

  1. Determine relations and base foreign keys on that. (Take a look at this postto get some inspiration.)
  2. Add more data types to the switch.
  3. ...
  1. 确定关系并以此为基础的外键。(看看这篇文章以获得一些灵感。)
  2. 将更多数据类型添加到switch.
  3. ...

Save the following trait as app/SchemaBuilder.php:

将以下特征另存为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;
    }
}

Create the following controller and register a route so that you can access it:

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

<?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();


    }
}

回答by Polaris

Here is a composer package that you can install that creates database tables from your models. It's called reliese.

这是一个 Composer 包,您可以安装它,从您的模型创建数据库表。它被称为依赖。

https://github.com/reliese/laravel

https://github.com/reliese/laravel

Hope this helps and is what you are looking for.

希望这会有所帮助,这正是您正在寻找的。

回答by Aakash Tushar

Run php artisan migratein the console. This will generate tables for definition existing in your database/migrationsfolder as shown in the pic in the question.

php artisan migrate在控制台中运行。这将生成用于定义database/migrations文件夹中存在的表,如问题中的图片所示。