正如其他人所指出的:这不是 Laravel 或者准确地说是 Eloquent ORM 的工作方式。通常,您首先创建一个表(即进行迁移),然后创建您的模型。坚持 Laravel model conventions 可以节省很多时间。
但是,您已经有一个或多个模型似乎缺少迁移。我建议您简单地为这些模型添加迁移。不幸的是,如果您有很多模型,尤其是(就像您的示例模型一样)当您不遵守表名和其他约定时,这将是很多工作。
另一方面,您的模型中已经有了很多要用于迁移的信息。您可以从 DocComments 和 $table、$primaryKey、$fillable 等属性中提取此信息。这可以自动完成。我整理了一个远未完成的示例,但至少应该让您开始了解迁移的基础。然后,您可以决定手动完成剩余部分或将功能添加到自动过程中。如果我有很多模型,我个人只会做后者。
示例
我基于您问题中包含的模型示例。
正如我所说;它远未完成,我想到了以下添加/改进:
- 确定关系并以此为基础的外键。 (看看这个post 以获得一些灵感。)
- 向
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();
}
}