Streams


Introduction

Simply put, a stream is a data structure. Technically streams are database tables.

The difference between streams and a database table is the streams API and generators. They let you quickly define, manage, and work with data in a robust, consistent, extensible, and easy to use way that extends past the data layer into presentation logic and UI.

Fields & Assignments

Fields represent attributes available to add to streams. The relation between the field and the stream is called an assignment. When a field is assigned to a stream a database column is typically created.

Field Types

Field types define the field's behavior. They control the field's form input, database storage and schema, accessor and mutator logic, presentation logic, validation, and more. Field types are an addon type so you can build your own if desired.

To put all this in to a para-code:

Consider the following data structure:

People -> Person -> Name -> Ryan

Classically defined as:

Database Table -> Row -> Column -> Value

Represented in streams as:

Stream -> Entry -> Field Assignment -> Field Type w/Value

Why use streams?

You might be wondering; why use the streams API instead of Laravel's migrations, schema builders, and Eloquent models to manage your data layer?

Because you have better things to do with your time.

By using the streams API you can quickly scaffold everything from the database structure and models, to form UI, validation, controllers, and literally everything we could think of in-between.

Using the streams API frees up huge amounts of time to focus on the unique development needs for your project.

Because your products will be more consistent.

The streams API will help you normalize your team's output. Your team of developers will know what tools to expect, how they work, and where to find them just by letting the streams API handle the grunt of the work for them.

Because you can still use native Laravel as desired.

The streams API and Pyro in general extends and is built atop the core concepts of Laravel. Streams is not at all a replacement of Laravel but a supplement for it. Like a development kit.

Because automation is awesome!

For example, streams are typically defined in migrations just like typical database table migrations. Unlike using the schema builder however, you get a lot more bang for your buck.

Using schema builder

The following code will yield a database table.

Schema::create(
    'people',
    function (Blueprint $table) use ($stream) {
        $table->increments('id');
        $table->integer('sort_order')->nullable();
        $table->datetime('created_at');
        $table->integer('created_by_id')->nullable();
        $table->datetime('updated_at')->nullable();
        $table->integer('updated_by_id')->nullable();
        $table->datetime('deleted_at')->nullable();
        $table->string('first_name');
        $table->string('last_name')->nullable();
        $table->string('email');
        $table->string('company')->nullable();
        $table->string('phone')->nullable();
        $table->string('address')->nullable();
        $table->string('city')->nullable();
        $table->integer('postal_code')->nullable();
        $table->string('country')->nullable();
        $table->string('state')->nullable();
        $table->string('tax_number')->nullable();
    }
);

$table->unique('email');
Using streams API

The following code will also yield a database table.

It also generates a complete set of tools for working with, managing, and presenting the data entries within the stream. Some of the tools you might already be familiar with from Laravel and some might be new:

  • An entry repository with interface
  • An entry model with interface
  • An entry collection
  • An entry presenter
  • An entry observer
  • An entry router
  • An entry table builder
  • An entry form builder
  • An entry plugin helper
  • CRUD controller/routes

The following example is also within a migration class.

protected $fields = [
    'first_name'       => 'anomaly.field_type.text',
    'last_name'        => 'anomaly.field_type.text',
    'email'            => 'anomaly.field_type.email',
    'company'          => 'anomaly.field_type.text',
    'phone'            => 'anomaly.field_type.text',
    'address'         => 'anomaly.field_type.textarea',
    'city'             => 'anomaly.field_type.text',
    'postal_code'      => 'anomaly.field_type.integer',
    'country'          => 'anomaly.field_type.country',
    'state'            => 'anomaly.field_type.state',
    'tax_number'       => 'anomaly.field_type.text',
];

protected $stream = [
    'slug'         => 'people',
    'title_column' => 'last_name',
    'trashable'    => true,
];

protected $assignments = [
    'first_name' => [
        'required' => true,
    ],
    'last_name',
    'email'      => [
        'required' => true,
        'unique'   => true,
    ],
    'tax_number',
    'company',
    'phone',
    'address',
    'city',
    'postal_code',
    'country',
    'state',
];
There's more!

Subsequently, any changes to the stream or fields either by API or programmatically, results in the database structure and base models automatically updating to mirror your changes.