2
votes

If I have two existing DataObjects that share common data & behavior, say for example they both have a Title field in the $db variable & I want to move the shared data into a base class for the two DataObjects, if I already have data in the database associated with the DataObject how do I migrate this data along with the structure, without having to get bogged down in sql? or is there no other way to do it?

So say my two DataObjects get their Title data by inheriting from BaseDataObject for example, this data in the DB moves to a table called BaseDataObject only the existing Title data wont migrate, obviously, how do i go about migrating it?

Edit:

I accepted the answer below even though it wasn't the solution to my problem.

I'd say the accepted answer is more relevant to the question of migrating data, however, to solve my issue of wanting a field shared across multiple DataObjects, but declared in one place while keeping the current database structures the same, I went with extending the classes via the DataExtension class and applying them that way.

1

1 Answers

1
votes

Normally I create a BuildTask for these tasks. Sometimes you'll have to do more complicated migrations than you could do with SQL alone (altough in your specific case SQL alone would be fine) and it's easier than writing a custom PHP script, because you can leverage the power of the SilverStripe framework. Here's the basic structure:

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

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

This task will then show up when you enter http://yoursite.com/dev/tasks

In your case it might be sufficient to get all the DataObjects, iterate through them and perform a forced write on them (eg. $dataObect->write(false, false, true);). Check if that did write the Title over from the Subclass to the base-class.. if that's the case, you can safely remove the Title field from the subclass-table. Otherwise you'll have to perform some slightly more low-level procedure. Maybe something along these lines:

$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"');

As soon as the migration is complete, you can set the $enabled variable to false, so that the task is no longer available.