MÀrk: Finessen databasmigrering har varit tillgÀnglig sedan version 1.1.6.
Likt kÀllkod vidareutvecklas strukturen för en databas över tid under utveckling och förvaltning av en databasdriven applikation. Till exempel under pÄgÄende utveckling, kan vi behöva lÀgga till en ny tabell; nÀr applikationen gÄtt i produktion kan vi upptÀcka behov av att lÀgga till ett index för en kolumn. Dat Àr viktigt att hÄlla reda pÄ sÄdana strukturella databasÀndringar (benÀmnda migration), sÄ som vi gör med vÄr kÀllkod. Om kÀllkod och databas kommer ur synk, Àr det mycket sannolikt att hela systemet kan fallera. Av denna anledning tillhandahÄller Yii ett verktyg för databasmigrering som kan hÄlla reda pÄ historik för datamigrering, applicera nya migreringar, eller ÄterstÀlla sÄdana som gjorts tidigare.
Följande steg belyser hur databasmigrering kan anvÀndas under utvecklingens gÄng:
Yii stöder databasmigrering via kommandoradsverktyget yiic migrate. Detta verktyg har stöd för att
skapa nya migreringar, applicera/ÄterstÀlla/upprepa migreringar samt för att visa migreringshistorik
och nya migreringar.
I det följande kommer vi att visa hur detta verktyg anvÀnds.
MÀrk: Det Àr bÀttre att anvÀnda applikationens instans av yiic (t.ex.
cd path/to/protected) vid arbete medmigrate-kommandot, i stÀllet för den iframework-katalogen. Kontrollera att katalogenprotected\migrationsexisterar och Àr möjlig att skriva till, samt att en databasanslutning Àr konfigurerad iprotected/config/console.php.
För att skapa en ny migrering (t.ex. skapa tabellen news), kör vi följande kommando:
yiic migrate create <name>
Den obligatoriska name-parametern specificerar en mycket kortfattad beskrivning
av migreringen (t.ex. create_news_table). Nedan framgÄr det att name-parametern
kommer att anvÀndas som en del i ett PHP-klassnamn. DÀrför skall den bara
innehÄlla bokstÀver, siffror och/eller understrykningstecken.
yiic migrate create create_news_table
OvanstÄende kommando kommer att, i katalogen protected/migrations, skapa en ny fil
med namnet m101129_185401_create_news_table.php vilken innehÄller följande initiala kod:
class m101129_185401_create_news_table extends CDbMigration
{
public function up()
{
}
public function down()
{
echo "m101129_185401_create_news_table does not support migration down.\n";
return false;
}
/*
// implementera safeUp/safeDown i stÀllet, om transaktioner skall anvÀndas
public function safeUp()
{
}
public function safeDown()
{
}
*/
}LÀgg mÀrke till att klassnamnet Àr samma som filnamnet enligt mönstret m<timestamp>_<name>,
dÀr <timestamp> refererar till UTC-tidstÀmpeln för nÀr migreringen skapats (pÄ formatet yymmdd_hhmmss),
och <name> hÀmtas frÄn kommandots name-parameter.
Metoden up() skall innehÄlla koden som implementerar den aktuella databasmigreringen,
medan metoden down() kan innehÄlla kod för att ÄterstÀlla det som sker i up().
Ibland Àr det inte möjligt att implementera down(). Om vi exempelvis tar bort tabellrader i up(),
kommer vi inte att kunna ÄterstÀlla dem i down(). I sÄdant fall kallas migreringen irreversibel,
med innebörden att vi inte kan backa till ett tidigare tillstÄnd för databasen. I den generarade
koden ovan, returnerar metoden down() vÀrdet false som indikation att migreringen inte Àr reversibel.
Info: Med start frÄn version 1.1.7 gÀller att returvÀrdet
falsefrÄm metodernaup()ochdown()medför att efterföljande migreringar annulleras. Tidigare, i version 1.1.6, krÀvdes att man genererade en exception för att övriga migreringar skulle annulleras.
Tag som exempel migreringen att skapa en news-tabell.
class m101129_185401_create_news_table extends CDbMigration
{
public function up()
{
$this->createTable('tbl_news', array(
'id' => 'pk',
'title' => 'string NOT NULL',
'content' => 'text',
));
}
public function down()
{
$this->dropTable('tbl_news');
}
}Basklassen CDbMigration erbjuder en uppsÀttning metoder för manipulering av data och databasens schema.
Till exempel, CDbMigration::createTable skapar en databastabell, medan CDbMigration::insert lÀgger till
en rad med data. Dessa metoder anvÀnder alla databasanslutningen som returneras av CDbMigration::getDbConnection(),
som standard Yii::app()->db.
Info: Noterbart Àr att databasmetoderna som CDbMigration erbjuder Àr mycket lika de i CDbCommand. Faktiskt sÄ Àr de likadana med undantaget att CDbMigration-metoderna mÀter tidÄtgÄng och skriver ut nÄgra meddelanden om metodparametrarna.
Info: Finessen transaktionella migreringar stöds sedan version 1.1.7.
Vid genomförande av komplexa DB-migreringar vill vi vanligen försÀkra oss om att samtliga migreringssteg utförs korrekt eller fallerar som en enhet, sÄ att databasen upprÀtthÄller korrekthet och integritet. För att uppnÄ detta mÄl kan vi dra nytta av DB-transaktioner.
Vi kan uttryckligen starta en DB-transaktion och lÄta transaktionen omge resterande DB-relaterad kod, pÄ följande sÀtt:
class m101129_185401_create_news_table extends CDbMigration
{
public function up()
{
$transaction=$this->getDbConnection()->beginTransaction();
try
{
$this->createTable('tbl_news', array(
'id' => 'pk',
'title' => 'string NOT NULL',
'content' => 'text',
));
$transaction->commit();
}
catch(Exception $e)
{
echo "Exception: ".$e->getMessage()."\n";
$transaction->rollBack();
return false;
}
}
// ...liknande kod för down()
}Ett enklare sÀtt att erhÄlla transaktionsstöd Àr att implementera metoden safeUp() i stÀllet för up(),
och metoden safeDown() i stÀllet för down(). Till exempel,
class m101129_185401_create_news_table extends CDbMigration
{
public function safeUp()
{
$this->createTable('tbl_news', array(
'id' => 'pk',
'title' => 'string NOT NULL',
'content' => 'text',
));
}
public function safeDown()
{
$this->dropTable('tbl_news');
}
}NÀr migreringen utförs kommer Yii att starta en DB-transaktion och dÀrefter anropa safeUp() eller safeDown().
Om nÄgot DB-fel intrÀffar i safeUp() eller safeDown(), kommer transaktionen att reverseras och dÀrmed
sÀkerstÀlla att databasen förblir i ett gott skick.
MÀrk: Transaktioner stöds inte av alla databashanterare. Vissa DB-frÄgor kan inte ingÄ i en transaktion. I sÄdant fall mÄste i stÀllet
up()ochdown()implementeras. I frÄga om MySQL, kan vissa SQL-satser leda till en underförstÄdd commit-operation.
För att applicera alla tillgÀngliga nya migreringar (dvs göra den lokala databasen helt up-to-date), kör följande kommando:
yiic migrate
Kommandot kommer att presentera en lista över alla nya migreringar. Efter bekrÀftelse att migreringarna
skall appliceras, kommer metoden up() i varje ny migreringsklass att exekveras, en efter en, i den ordning
tidstÀmpelvÀrden i klassnamnen anger.
Efter applicering av en migrering kommer migreringsverktyget att spara en post i databastabellen tbl_migration.
Detta möjliggör för vektyget att hÄlla reda pÄ vilka migreringar som applicerats och vilka som inte har applicerats.
Om tabellen tbl_migration inte existerar, kommer verktyget att automatiskt skapa den i databasen som specificeras
av applikationskomponenten db.
Ibland vill vi bara applicera en eller ett fÄtal nya migreringar. Följande kommando kan dÄ anvÀndas:
yiic migrate up 3
Detta kommando applicerar tre nya migreringar. Genom att Àndra vÀrdet (3) kan vi Àndra antalet migreringar som skall appliceras.
Vi kan Àven migrera databasen till en specifik version, med följande kommando:
yiic migrate to 101129_185401
Det vill sÀga, vi anvÀnder tidstÀmpeldelen av migreringens namn för att specificera den version vi vill migrera databasen till. Om det finns flera migreringar mellan den senast applicerade och den specificerade migreringen kommer samtliga dessa migreringar att appliceras. Om den specificerade migreringen redan har applicerats tidigare, kommer alla migreringar som applicerats dÀrefter att ÄterstÀllas (kommer att beskrivas i nÀsta avsnitt).
För att backa tillbaka den senaste eller flera applicerade migreringar, kan följande kommando anvÀndas:
yiic migrate down [step]
dÀr den frivilliga step-parametern specificerar antalet migreringar som skall backas tillbaka.
Som standard Àr den 1, vilket innebÀr att den senaste migreringen backas.
Som tidigare beskrivits kan inte alla migreringar backas. Försök att backa irreversibla migreringar kommer att generera ett undantag och innebÀr att hela ÄterstÀllningsprocessen stoppas.
Att göra om migreringar innebÀr att först backa och sedan pÄ nytt applicera de specificerade migreringarna. Detta kan göras med följande kommando:
yiic migrate redo [step]
dÀr den frivilliga step-parametern specificerar antalet migreringar som skall göras om. StandardvÀrde 1,
med innebörden att göra om den senaste migreringen.
Utöver att applicera och backa tillbaka migreringar, kan migreringsverktyget Àven presentera migrationshistorik och de nya migreringar som vÀntar pÄ att appliceras.
yiic migrate history [limit] yiic migrate new [limit]
dÀr den frivilliga parametern limit specificerar antalet migreringar som skall visas. Om limit utelÀmnas,
kommer samtliga tillgÀngliga migreringar att visas.
Det första kommandot visar de migeringar som har applicerats medan det andra kommandot visar de migreringar som Ànnu ej applicerats.
Ibland kan vi ha för avsikt att Àndra migreringshistoriken till en specifik version, utan att faktiskt applicera eller backa tillbaka de relevanta migreringarna. Detta intrÀffar ofta under utveckling av en ny migrering. Följande kommando kan anvÀndas för detta ÀndamÄl.
yiic migrate mark 101129_185401
Detta kommando Àr snarlikt yiic migrate to-kommandot, med undantag för att det enbart Àndrar tabellen med
migreringshistorik till den specificerade versionen utan att applicera eller backa tillbaka migreringarna.
Migreringskommandot kan anpassas pÄ mÄnga sÀtt.
Migreringskommandot har fyra inbyggda alternativ som kan specificeras pÄ kommandoraden:
interactive: boolean, specificerar huruvida migrering skall utföras i interaktivt lÀge.
Som standard true, vilket innebÀr att anvÀndaren tillfrÄgas nÀr en specifik migrering skall utföras.
SÀtt till false i hÀndelse migreringarna skall utföras i en bakgrundsprocess.
migrationPath: string, specificerar katalogen som lagrar alla migreringars klassfiler.
Detta mÄste specificeras som ett sökvÀgsalias och den motsvarande katalogen mÄste existera.
Om alternativet utelÀmnas kommer underkatalogen migrations till applikationens basePath att anvÀndas.
migrationTable: string, specificerar namnet pÄ den databastabell som lagrar migreringshistoriken.
Som standard Àr det tbl_migration. Tabellstrukturen Àr version varchar(255) primary key, apply_time integer.
connectionID: string, specificerar ID för databasens applikationskomponent. Ăr som standard 'db'.
templateFile: string, specificerar sökvÀgen för den fil som skall tjÀnsgöra som kodmall för generering
av migreringsklasserna. Denna mÄste specificeras som ett sökvÀgsalias (t.ex. application.migrations.template).
Om alternativet utelÀmnas kommer en intern mall att anvÀndas. Inuti kodmallen kommer symbolen {ClassName}
att ersÀttas av det faktiska namnet pÄ migreringsklassen.
För att specificera dessa alternativ, exekvera migreringskommandot pÄ följande format
yiic migrate up --option1=value1 --option2=value2 ...
Till exempel, om vi vill migrera för en modul forum, vars migreringsfiler Àr placerade i modulens
underkatalog migrations, kan vi anvÀnda följande kommando:
yiic migrate up --migrationPath=ext.forum.migrations
Medan kommandoradsalternativ tillÄter oss att konfigurera migreringskommandot i farten, kan vi ibland vilja konfigurera kommandot en gÄng för alla. Till exempel kan vi vilja anvÀnda en annan tabell för lagring av migreringshistoriken, eller vi kanske vill anvÀnda en anpassad migreringsmall. Detta kan vi göra genom att modifiera konsolapplikationens konfigurationsfil sÄ som följer,
return array(
......
'commandMap'=>array(
'migrate'=>array(
'class'=>'system.cli.commands.MigrateCommand',
'migrationPath'=>'application.migrations',
'migrationTable'=>'tbl_migration',
'connectionID'=>'db',
'templateFile'=>'application.migrations.template',
),
......
),
......
);Om vi nu kör migrate-kommandot, kommer ovanstÄende konfigureringar att gÀlla, utan att vi behöver
mata in kommandoradsalternativ varje gÄng.
Found a typo, or you think this page needs improvement?
Edit it on GitHub !
Signup or Login in order to comment.