我正试图弄清楚如何处理Laravel 5.2中迁移中的结构和数据相关变化。 目前,我只是在对数据库进行结构更改后更改现有数据。 但这似乎与版本控制的代码相冲突。
应将owner_id
列添加到teams
表中。简单的迁移,没问题。之后,所有现有的团队都应该获得这样的身份。因此我也把它放在迁移中:
foreach ($teams as $team) {
// get the first user of this team over a many-to-many-relationship-table `team_user`
$team->owner_id = $team->users->first()->id;
...
}
乍一看,工作正常。
几天后,我决定在上述关系表中添加一个数据透视列role
。我添加了迁移,在团队模型中我添加了这样的内容:
public function users() {
return $this->belongsToMany(...)->withPivot('role');
}
如果我想现在完全刷新我的本地数据库,我将在第一次迁移时收到错误。那是因为它调用了$ team->用户,但是在数据库的这种状态下,role
尚不可用,因此方法调用失败。这就像版本控制和数据库迁移之间的转换。
这是否有一个干净的解决方案?
提前非常感谢, 理查德
答案 0 :(得分:2)
通常迁移是DDL(数据定义语言),种子是DML(数据操作语言)。
迁移数据库表是一个有序的问题。您无法添加依赖于某些DDL的代码,这些代码可能会在运行这些DDL之前执行。
您必须考虑的另一件事是:迁移不是进行数据播种,修改和操作的地方,因为播种可能需要在开始播种之前完成所有数据定义。这就是为什么Laravel有数据播种的原因。
因此,播种,修复和更改数据之间没有区别,它是所有DML。您可以在迁移中执行此操作,但这不是禁止的,但在那些您必须非常小心地撤消(向下)您在up
方法中执行的每个步骤时。但有时候操纵数据太难了。
您的问题是您正在尝试通过关系访问某些数据,这些数据尚未准备好(或已完成或播种),因为尚未运行的迁移尚未运行。因此,DDL和DML之间存在冲突,如果单独处理它们就不会发生冲突。
通常数据播种仅用于测试,但如果您真的需要它,您可以在播种机中执行以下操作:
<?php
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
if (app()->environment('testing')) {
$this->call(TestingSeeders::class);
}
$this->call(ProductionReadySeeders::class);
}
}
或者您可以创建一个命令来播种数据:
Artisan::command('app:seed', function ($email)
{
// Do whatever you need to seed your database tables
});
用
运行php artisan app:seed
如果您想确保每个获得新版本的人如果您的应用也获得了正确的数据,您可以使用Composer后执行命令来执行此操作:
"post-install-cmd": [
"Illuminate\\Foundation\\ComposerScripts::postInstall",
"php artisan optimize",
"php artisan migrate --force",
"php artisan app:seed"
],
"post-update-cmd": [
"Illuminate\\Foundation\\ComposerScripts::postUpdate",
"php artisan optimize",
"php artisan migrate --force",
"php artisan app:seed"
]