Propel 1.6.9 migrations (data) - Possible to implement the 'down' command using PDO only?

StackOverflow https://stackoverflow.com/questions/20542876

  •  31-08-2022
  •  | 
  •  

문제

I've just upgraded the Propel in a legacy project from 1.4 to 1.6.9 and am trying to make use of the migration functionality. In doing some tests, I've realised that when doing a data migration (no schema changes) it's possible to use PDO classes to manage inserting/updating the new data, but the same isn't true for the 'down' part of the same migration.

Or rather, it will execute the PDO aspect of the preDown() method, but because nothing is executed from the getDownSQL() method then it doesn't change the current migration version stored in the database. This is obviously a problem as it won't let me re-apply the migration again unless I manually change the version number, which I don't want to get in the habit of doing.

For example, here's the 'up' part of the migration: (the version number IS incremented accordingly after running this despite getUpSQL() returning an empty array)

public function preUp(PropelMigrationManager $manager)
{
    $property = new Property();
    $property
        ->setName('blahblah')
        ->setDescription('Test property')
        ->setEditable(1)
        ->save()
    ;
}

And here's what I want to do in my postDown(): (I've realised using preDown() for this is a bad idea - I don't want changes to be out of sync with the version number)

public function postDown(PropelMigrationManager $manager)
{
    $query = new PropertyQuery();
    $property = $query->findOneByName('blahblah');
    $property->delete();
}

At the moment the down isn't being executed because getDownSQL() returned nothing. I can get it to work using SQL for the down direction like so...

    public function getDownSQL()
    {
        return array(
            'source' => "
DELETE FROM properties WHERE name = 'blahblah' LIMIT 1;
            "
        );
    }

...but I'd prefer not to have to do this if possible. So does anyone know if I can force it to think that it's made changes even when there are none so I can make use of the postDown() way instead and have the version number be changed accordingly? Thanks.

도움이 되었습니까?

해결책

I managed to resolve this issue myself. I'd already written a console command that generates an empty Propel migration based on a custom template so that I could have data only migrations. I just made it so these generated migration classes extend a common BaseMigration class elsewhere that contains the following methods: (plus a few more, but they aren't important here)

/**
 * Force the version to the version of this migration. Useful for data migrations only using preUp()
 *
 * @param PropelMigrationManager $manager
 */
protected  function updateToCurrentVersion(PropelMigrationManager $manager)
{
    $manager->updateLatestMigrationTimestamp($this->getCurrentDatasource($manager), $this->getCurrentVersion());
}

/**
 * This method should be called if implementing the down functionality using PDO in the preDown() method
 *
 * @param PropelMigrationManager $manager
 */
protected function updateToPreviousVersion(PropelMigrationManager $manager)
{
    $datasource = $this->getCurrentDatasource($manager);
    $currentVersion = $this->getCurrentVersion();

    $timestamps = $manager->getAlreadyExecutedMigrationTimestamps();
    rsort($timestamps);

    $previousVersion = 0;
    foreach ($timestamps as $timestamp) {
        if ($timestamp < $currentVersion) {
            $previousVersion = $timestamp;
            break;
        }
    }

    $manager->updateLatestMigrationTimestamp($datasource, $previousVersion);
}

/**
 * @return int
 */
protected function getCurrentVersion()
{
    $class = get_class($this);

    return (int) substr($class, strpos($class, '_') + 1);
}

Now I just need to call $this->updateToCurrentVersion($manager) from the end of preUp() method (see note below) and $this->updateToPreviousVersion($manager) at the end of the preDown() method to force the version numbers to update correctly.

NOTE: I noticed that the version wasn't updated when running the "up" migration command to only perform a single migration, whereas it would be updated when running "migrate"...even if this was applying the same migration! So it's safer to force the current version to be updated all the time.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top