laravel从模型生成数据库

时间:2018-07-03 15:57:21

标签: php laravel artisan

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

我的问题是,有了这个Model,是否可以通过php artisan从该模型创建数据库表?如果有一个php artisan命令可以对我所有的模型进行超级处理。

在我的数据库文件夹中,有这些,但我不知道它们的作用。

enter image description here

5 个答案:

答案 0 :(得分:4)

如果您希望自动生成这些表,则不会,Laravel确实没有办法做到这一点。从理论上讲,您可以编写自己的命令来为每个模型生成迁移文件,但是无论如何仍然需要您提供所有列名,数据类型等。例如,看一下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"

    ...
}

答案 1 :(得分:1)

是否可以通过php artisan通过模型创建数据库表?

听起来您想要的是“代码优先设计”。 Microsoft的Entity Framework支持此功能,但是Laravel的工作方式有所不同。在带有实体框架的C#中,将创建属性(基本上是getter方法)以与每个数据库列相对应。使用Eloquent(Laravel的ORM库),它可以使用PHP magic methods动态生成这些代码,PHP变量也缺乏C#的类型。因此,无法以所需的方式基于代码填充数据库。您在问题中发布的文档注释看起来像是使用laravel-ide-helper包从数据库到代码的另一种生成方式。

或者,某些数据库客户端(例如Sequel Pro)具有将现有数据库架构导出到Laravel迁移中的插件,我发现它在过去非常快速且有用,并且可能是与工作流程最接近的东西正在寻找。祝你好运!

Exporting a database schema as a Laravel migration

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

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

php artisan migrate

答案 2 :(得分:0)

正如其他人指出的那样:Laravel或确切地说是雄辩的ORM并不是这样工作的。通常,您首先要创建一个表(即进行迁移),然后再创建模型。坚持使用Laravels model conventions可以节省很多时间。

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

另一方面,您已经有很多要迁移的信息,可以在模型中使用。您可以从DocComments和$table$primaryKey$fillable等属性中提取此信息。这可以自动完成。我整理了一个远未完成的示例,但至少应该使您从迁移的基础入手。然后,您可以决定手动完成其余部分,或为自动过程添加功能。如果我有很多模型,我个人只会做后者。


示例

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

正如我所说;还远远不够,请注意以下新增/改进:

  1. 确定关系并以此为基础建立外键。 (看看这个post可以得到一些启发。)
  2. switch添加更多数据类型。
  3. ...

将以下特征保存为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();


    }
}

答案 3 :(得分:0)

这是您可以安装的Composer程序包,可从您的模型创建数据库表。这就是所谓的依赖。

https://github.com/reliese/laravel

希望这对您有所帮助。

答案 4 :(得分:-2)

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