在SilverStripe中重构数据库时迁移数据

时间:2013-10-01 12:26:43

标签: silverstripe

如果我有两个现有的DataObjects共享公共数据&例如,他们在$ db变量&中都有一个Title字段。我想将共享数据移动到两个DataObjects的基类中,如果我已经在与DataObject关联的数据库中有数据,我该如何将这些数据与结构一起迁移,而不必陷入sql陷入困境?或者没有别的办法吗?

所以说我的两个DataObjects通过继承Title得到他们的BaseDataObject数据,例如,数据库中的这些数据移动到一个名为BaseDataObject的表只有现有{ {1}}数据不会迁移,显然,我该如何迁移呢?

修改

我接受了下面的答案,即使它不能解决我的问题。

我说接受的答案与迁移数据的问题更相关,但是,要解决我想要跨多个Title共享字段但在一个地方中声明的问题保持当前数据库结构不变,我通过DataObjects类扩展类并以这种方式应用它们。

1 个答案:

答案 0 :(得分:1)

通常我会为这些任务创建BuildTask。有时你需要进行比单独使用SQL更复杂的迁移(尽管在特定情况下单独使用SQL就可以了)并且它比编写自定义PHP脚本更容易,因为您可以利用SilverStripe框架的强大功能。这是基本结构:

class MigrateTask extends BuildTask
{
    protected $title = 'Task title';
    protected $description = 'Task description';
    protected $enabled = true;

    public function run($request) {
        // perform your migrations here
    }
}

当您输入http://yoursite.com/dev/tasks

时,此任务将会显示

在您的情况下,获取所有DataObjects,遍历它们并对它们执行强制write(例如$dataObect->write(false, false, true);)可能就足够了。检查是否确实将Title从Subclass写入基类..如果是这种情况,您可以安全地从子类表中删除Title字段。否则你将不得不执行一些稍微低级的程序。也许是这些方面的东西:

$rslt = DB::query('SELECT * FROM "DataObjectSubclass"');
foreach($rslt as $r){
    DB::query('UPDATE "DataObjectBaseClass" SET "Title" = \''. $r['Title'] .'\' WHERE ID = '. $r['ID']);
}

// you could even drop the title field once you're done.. 
// But you'll have to be sure that the above code migrated your data
// correctly. Otherwise you're screwed ;)
DB::query('ALTER TABLE "DataObjectSubclass" DROP "Title"');

迁移完成后,您可以将$enabled变量设置为false,以便该任务不再可用。