Migrations

Introduction

In general migrations in the Streams Platform work just like migrations in Laravel. Except now you can leverage the streams, fields, and assignments repositories to scaffold your database automatically.

Migrations in the database/migrations directory are ran last during system installation.{.tip}

Generating Migrations

You can generate migrations just like you normally would using make:migration with the addition of a few options.

Addon Migrations

To target a specific addon to generate your migration in you can use the --addon option:

php artisan make:migration change_phone_to_text_field_type --addon=anomaly.module.contacts

Default Migrations

You can also create "normal" migrations by omitting the --fields and --stream options. This will create a migration very similar to Laravel migrations with the exception that the fields, streams, and assignments repositories are all available to use.

php artisan make:migration make_widgets_trashable --addon=example.module.test

Then populate your migration:

<?php

use Anomaly\Streams\Platform\Database\Migration\Migration;

class AnomalyModulePagesMakePagesSearchable extends Migration
{

    public function up()
    {
        $stream = $this->streams()->findBySlugAndNamespace('widgets', 'example');

        $stream
            ->setAttribute('trashable', true)
            ->save();
    }

    public function down()
    {
        $stream = $this->streams()->findBySlugAndNamespace('widgets', 'example');

                $stream
                    ->setAttribute('trashable', false)
                    ->save();
    }
}

Migration Types

Stream Migrations

You can create streams via stream repositories directly but you may prefer using a stream migration to simplify things. You can create a stream migration by using --stream=stream_slug option.

php artisan make:migration create_example_stream --addon=example.module.test --stream=widgets

Then populate your migration:

<?php

use Anomaly\Streams\Platform\Database\Migration\Migration;

class AnomalyModuleTestCreateWidgetsStream extends Migration
{

    protected $delete = true; // Delete stream on rollback

    protected $stream = [
        'slug'         => 'widgets',
        'title_column' => 'name',
        'translatable' => true,
        'searchable'   => false,
        'trashable'    => true,
    ];

    protected $assignments = [
        'name'        => [
            'required'     => true,
            'translatable' => true,
        ],
        'slug'        => [
            'required' => true,
            'unique'   => true,
        ],
        'description' => [
            'translatable' => true,
        ],
    ];
}

Field Migrations

You can create fields via field repositories directly but you may prefer using a field migration to simplify things. You can create a field migration by using the --fields option flag.

php artisan make:migration create_more_fields --addon=example.module.test --fields

Now you can populate the generated migration:

<?php

use Anomaly\Streams\Platform\Database\Migration\Migration;

class AnomalyModuleTestCreateMoreFields extends Migration
{

    protected $fields = [
        'first_name' => 'anomaly.field_type.text',
        'last_name' => 'anomaly.field_type.text',
        'siblings' => [
            'type'   => 'anomaly.field_type.multiple',
            'config' => [
                'mode' => 'lookup',
                'related' => \Anomaly\TestModule\Person\PersonModel::class,
            ],
        ],
    ];

}

And lastly run the migration:

php artisan migrate --addon=anomaly.module.test

Appending Stream Data

Often times you will need to append streams information by adding fields, assignments, or updating streams.

Using Definitions

<?php

use Anomaly\Streams\Platform\Database\Migration\Migration;

class AnomalyModuleTestAddExampleField extends Migration
{

    /**
     * Don't delete stream on rollback
     * because this isn't creating the
     * stream only referencing it.
     */
    protected $delete = false;

    /**
     * Any additional information will
     * be updated. Slug helps find
     * the stream to work with for
     * assignments that follow.
     */
    protected $stream = [
        'slug' => 'widgets',
    ];

    /**
     * This field will be added.
     */
    protected $fields = [
        'example' => 'anomaly.field_type.boolean',
    ];

    /**
     * These assignments will be
     * created for the stream above.
     */
    protected $assignments = [
        'example'        => [
            'required'     => true,
            'translatable' => true,
        ],
    ];

}

Using Repositories

You can also use the fields, streams, and assignments repositories bundled in the migration.

<?php

use Anomaly\Streams\Platform\Database\Migration\Migration;

class AnomalyModulePagesMakePagesSearchable extends Migration
{

    public function up()
    {
        $stream = $this->streams()->findBySlugAndNamespace('widgets', 'example');

        $stream
            ->setAttribute('trashable', true)
            ->save();
    }

    public function down()
    {
        $stream = $this->streams()->findBySlugAndNamespace('widgets', 'example');

                $stream
                    ->setAttribute('trashable', false)
                    ->save();
    }
}

Defining Custom Namespaces

When creating field you must provide a namespace to create the fields in. By default the slug of the addon the migration resides in will be used as the namespace. You can also define the $namespace property if the addon slug does not suffice:

protected $namespace = 'example';

Lastly you can define the namespace inline with the stream and and assignment definitions:

protected $stream = [
    'slug' => 'widgets',
    'namespaces' => 'example',
    'title_column' => 'name',
    'translatable' => true,
    'trashable' => true,
];

protected $assignments = [
    'name' => [
        'namespace' => 'example',
        'translatable' => true,
        'required' => true,
    ],
];

Being able to set the namespace like this means you can create streams and assign fields for any namespace from anywhere without modifying core code.{.tip}