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