Before starting our app we need to run any migrations, install Passport keys, cache our event handlers, cache views, config and routes, load our read models to Redis and start the server.

We'll create two commands with the first command handling the first four tasks and the second command handling the last two.

Run php artisan make:command Init and `php artisan make:command LoadStoreAndServe.

Replace the contents of the Init command with:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\ProcessUtils;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Process\PhpExecutableFinder;
use Illuminate\Support\Facades\Artisan;

class Init extends Command {
  /**
  * The name and signature of the console command.
  *
  * @var string
  */
  protected $signature = 'init';

  /**
  * The console command description.
  *
  * @var string
  */
  protected $description = 'Do some housekeeping, then call the command to start the server';

  /**
  * Execute the console command.
  *
  * @return mixed
  */
  public function handle() {
    $this->line('<info>Cache config, views and routes...</info>');
    $this->call('config:cache');
    $this->call('view:cache');
    $this->call('route:cache');
    
    $this->line('<info>Run migrations...</info>');
    $this->call('migrate', ['--force']);

    $this->line('<info>Install passport keys...</info>');
    $this->call('passport:install');

    $this->line('<info>Cache event handlers...</info>');
    $this->call('event-projector:cache-event-handlers');

    $this->call('load:serve');
  }
}

Replace the contents of the LoadStoreAndServe command with:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Spatie\EventProjector\Projectionist;

class LoadStoreAndServe extends Command {
  /**
   * The name and signature of the console command.
   *
   * @var string
   */
  protected $signature = 'load:serve';

  /**
   * The console command description.
   *
   * @var string
   */
  protected $description = 'Load read store, then start the server';

  /** @var \Spatie\EventProjector\Projectionist */
  protected $projectionist;

  /**
   * Create a new command instance.
   *
   * @return void
   */
  public function __construct(Projectionist $projectionist) {
    parent::__construct();

    $this->projectionist = $projectionist;
  }

  /**
   * Execute the console command.
   *
   * @return mixed
   */
  public function handle() {
    $this->line("<info>Build read model...</info>");
    $this->replay();

    return $this->call('serve', ['--host' => env('APP_HOST', '0.0.0.0')]);
  }

  private function replay(): void {
    $storeEventClass = config('event-projector.stored_event_model');

    $replayCount = $storeEventClass::startingFrom(0)->count();

    if ($replayCount === 0) {
      $this->warn('There are no events to replay');
      return;
    }

    $this->comment("Replaying $replayCount events...");

    $bar = $this->output->createProgressBar($storeEventClass::count());

    $this->projectionist->replay($this->projectionist->getProjectors(), 0, function () use ($bar) { $bar->advance(); });
    $bar->finish();
    $this->emptyLine(2);
  }

  private function emptyLine(int $amount = 1): void {
    foreach (range(1, $amount) as $i) $this->line('');
  }
}

Now, we start our app by running php artisan init.

You can view changes here.