Using

migrations & fixtures

Miro Svrtan

@msvrtan

Migrations

Server migrations

Database system migrations

Schema migrations

Schema migrations

Model schema

Database schema

Create migration

Calculate differences

Create migration file

Model schema

Database schema

Source of truth!

Calculate differences

Create migration file

<?php

namespace DoctrineMigrations;

use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;

class Version2 extends AbstractMigration
{
    public function up(Schema $schema)
    {
        $this->addSql('CREATE TABLE user (id INT NOT NULL, username VARCHAR(180), ...)');
        $this->addSql('CREATE UNIQUE INDEX UNIQ_957A6479C05FB297 ON user (username)');
    }

    ...
}

Version2

Version1

Run migration

Any new migrations?

Run migration `Version2`

Version1

Mark migration `Version2` as run

Version2

Version2

Run migration (again)

Any new migrations?

Nope, I'm done

Version1

Version1

<?php

namespace DoctrineMigrations;

use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;

class Version2 extends AbstractMigration
{
    public function up(Schema $schema)
    {
        $this->addSql('CREATE TABLE user (id INT NOT NULL, username VARCHAR(180), ...)');
        $this->addSql('CREATE UNIQUE INDEX UNIQ_957A6479C05FB297 ON user (username)');
    }

    public function down(Schema $schema)
    {        
        $this->addSql('DROP TABLE user');
    }
}

Move forward/       no rollbacks     

<?php

namespace DoctrineMigrations;

use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;

class Version20181027165500 extends AbstractMigration
{
    public function up(Schema $schema)
    {
        ...
    }

    public function down(Schema $schema)
    {        
        ..
    }
}

Versioning

<?php

namespace DoctrineMigrations;

use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;

class Version20181027165500 extends AbstractMigration
{
    public function up(Schema $schema)
    {
        $this->abortIf('postgresql' !== $this->getDatabasePlatform(), 
            'Migration can only be executed safely on \'postgresql\'.');

        $this->addSql('CREATE TABLE user (id INT NOT NULL, username VARCHAR(180), ...)');
        $this->addSql('CREATE UNIQUE INDEX UNIQ_957A6479C05FB297 ON user (username)');
    }

    public function down(Schema $schema)
    {        
        $this->abortIf('postgresql' !== $this->getDatabasePlatform(), 
            'Migration can only be executed safely on \'postgresql\'.');

        $this->addSql('DROP TABLE user');
    }
}

Locked to vendor

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUserTable extends Migration
{
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            ...

        });
    }

    public function down()
    {
        Schema::drop('users');
    }
}

Laravel migrations

Deployment

Deploying on large datasets

Fixtures

'dummy' instead of production data

Fixtures

<?php

namespace App\DataFixtures\ORM;

use App\Entity\User;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\Persistence\ObjectManager;

class UsersFixtures extends AbstractFixture
{
    public function load(ObjectManager $manager)
    {
        $user1 = new User();
        $user1->setId(1);
        $user1->setUsername('username1');
        $user1->setEmail('username1@example.com');

        $user2 = new User();
        $user2->setId(2);
        $user2->setUsername('username2');
        $user2->setEmail('username2@example.com');

        $manager->persist($user1);
        $manager->persist($user2);

        $manager->flush();
    }

}
<?php

namespace App\DataFixtures\ORM;

use App\Entity\User;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\Persistence\ObjectManager;

class UsersFixtures extends AbstractFixture
{
    public function load(ObjectManager $manager)
    {
        for ($i = 1; $i < 10; $i++) {

            $user = new User();
            $user->setId($i);
            $user->setUsername('username'.$i);
            $user->setEmail('username'.$i.'@example.com');

            $manager->persist($user);
        }

        $manager->flush();
    }

}
<?php

namespace App\DataFixtures\ORM;

use App\Entity\User;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\Persistence\ObjectManager;

class UsersFixtures extends AbstractFixture
{
    public function load(ObjectManager $manager)
    {
        for ($i = 1; $i < 10; $i++) {

            $user = new User();
            $user->setId($i);
            $user->setUsername('username'.$i);
            $user->setEmail('username'.$i.'@example.com');

            $manager->persist($user);
        }

        $manager->flush();
    }

}
<?php

namespace App\DataFixtures\ORM;

..

class UsersFixtures extends AbstractFixture
{
    public function load(ObjectManager $manager)
    {
        $alex = new User();
        $alex->setId(1);
        $alex->setUsername('alex');
        $alex->setEmail('alex@example.com');

        $sasha = new User();
        $sasha->setId(2);
        $sasha->setUsername('sasha');
        $sasha->setEmail('sasha@example.com');

        $manager->persist($alex);
        $manager->persist($sasha);

        $manager->flush();
    }

}

Proper naming!

Demo time

Thank you!

Miro Svrtan

@msvrtan

miro (at) mirosvrtan.me

Any questions?

Using migrations and fixtures

By Miro Svrtan

Using migrations and fixtures

  • 2,430