I've been exploring the code base for Magento 2 and I've been trying to figure how you can control the order in which upgrade setup classes would run between setup versions. Yet, i'm stuck. As far as my digging has taken me I haven't been able to find a way to control the order of schema/data upgrades within my module.
To give a little context, let's say I release a module. Overtime we release updates. Let's say I have the following file structure:
Setup/InstallPostSchema.php
Setup/CreateAuthorsTableSchema.php
Setup/AddAuthorIdColumnToPostSchema.php
In this case I'd want Setup/CreateAuthorsTableSchema.php
to run before Setup/AddAuthorIdColumnToPostSchema.php
.
My question is, how do/should we deal with that?
In Magento 1.x the file naming convention handled this for us: upgrade-1.0.0-1.1.0.php
for example.
Frameworks like Laravel, or Rails (and others i'm sure) use a timestamp approach. However, they also have a migrations table which would tell you each migration that has run so far. Also allowing for easy rollback.
Update
I have found an example of managing versioning yourself within the Magento/Customer
module:
public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context)
{
$setup->startSetup();
if (version_compare($context->getVersion(), '2.0.0.1') < 0) {
// Changes here.
}
if (version_compare($context->getVersion(), '2.0.1', '<')) {
// Changes here
}
$setup->endSetup();
}
Best Answer
There is a very strict standard for the naming of setup scripts. To my knowledge, you cannot name them arbitrarily and have them actually do anything on their own. See:
\Magento\Setup\Model\Installer::getSchemaDataHandler()
Your setup changes must fall within the appropriate class for what they're doing:
Setup\InstallSchema
Setup\UpgradeSchema
Setup\Recurring
Setup\InstallData
Setup\UpgradeData
Each one has a single install() or upgrade() entrypoint that Magento calls at the appropriate time.
You're asking about
UpgradeSchema
specifically: How you handle the upgrade process withinSetup\UpgradeSchema::upgrade()
is entirely up to you. You control the entire code and process. You could do it version-wise (check the current version, apply the appropriate changes to bring it up to date), or semantically (check the current schema and apply necessary changes, IE create authors table if it does not exist), or something else entirely.You could make each action or version its own method, or setup subclasses that you load and call explicitly. That's up to you.