Skip to content

Getting started with Flyokai

A 30-minute walkthrough from composer create-project to a running web API and a working DTO/schema.

1. Pick an edition

Edition Use it when
flyokai/webapi-edition You're building an HTTP/JSON API.
flyokai/data-service-edition You need socket-based async services on top of webapi-edition.

If you also need the Magento DTOs / cache backend, start from one of the editions and composer require flyokai/magento-dto flyokai/magento-amp-mate. To pull every framework module at once, composer require flyokai/flyokai (the metapackage).

composer create-project flyokai/webapi-edition my-api dev-dev
cd my-api

2. First-time install

vendor/bin/flyok-setup install \
    --db-host=localhost \
    --db-user=app \
    --db-pass=secret \
    --db-name=app \
    --base-url=http://localhost:8080

This installs runtime scripts in bin/, generates OAuth signing keys + dev TLS certs, and reconciles the database from any #[Table]-tagged Solid DTOs the framework can find. See setup-and-deploy.md for what each phase does.

3. Smoke test

php bin/flyok-console ping     # → { "result": "pong" }

# Create an admin user + an OAuth client
php bin/flyok-console acl:role:create --name admin '[]'
php bin/flyok-console user:create --uname=admin --email=admin@example.com --role=admin --pass='admin1234'
php bin/flyok-console oauth:client:create admin client_credentials

# Get a token
curl -X POST http://localhost:8080/token \
    -d grant_type=client_credentials \
    -d client_id= \
    -d client_secret=

Use the token in Authorization: Bearer … against any HTTP endpoint guarded by Flyokai\OauthServer\HandlerGuard\Authorization.

4. Add a DTO + a table

Create a Solid DTO in your project's source tree (or in a separate package you require):

use Flyokai\DataMate\Dto;
use Flyokai\DataMate\DtoTrait;
use Flyokai\DataMate\Solid;
use Flyokai\DbSchema\Attribute\{Table, Column, PrimaryKey};

#[Table(name: 'app_widget', alias: 'widget')]
final class WidgetSolid implements Dto, Solid
{
    use DtoTrait;

    public function __construct(
        #[PrimaryKey(autoIncrement: true)] public readonly int $widgetId,
        #[Column(length: 64)]                public readonly string $sku,
        public readonly float $price,
    ) {}
}

Run php bin/flyok-setup upgradedb-schema discovers the new #[Table] and emits a CREATE TABLE. Re-run anytime; it's idempotent.

5. Add an HTTP endpoint

Use the new-endpoint skill to scaffold a controller, register a route, and gate it with OAuth. Or by hand:

namespace App\Controller;

use Amp\Http\Server\HttpErrorException;
use Amp\Http\Server\Request;
use Amp\Http\Server\Response;
use Flyokai\OauthServer\HandlerGuard\ProtectedHandler;

final class GetWidget implements ProtectedHandler
{
    public function resourceId(): string { return 'widget.read'; }

    public function __construct(private readonly WidgetRepository $widgetRepo) {}

    public function handleRequest(Request $request): Response
    {
        $id     = (int) $request->getAttribute('routeArgs')['id'];
        $widget = $this->widgetRepo->getById($id);

        return new Response(200, ['content-type' => 'application/json'],
            json_encode($widget->toArray(), JSON_THROW_ON_ERROR));
    }
}

Register the route in your module's WebBootstrap::bootstrap():

$routerBuilder = $this->container->get('httpRouterBuilder:default');
$routerBuilder->addRoute('GET', '/api/widgets/{id}', $this->container->get(GetWidget::class));

Restart the HTTP server: php bin/flyok-console http:restart.

6. Run a search query

$result = $widgetRepo->getList([
    'AND' => [['field' => 'price', 'op' => 'gt', 'value' => 9.99]],
    'sort' => [['field' => 'sku', 'direction' => 'asc']],
    'limit' => 50,
    'withTotal' => true,
]);

flyokai/search-criteria validates fields, auto-discovers joins from #[ForeignKey], and emits parameterised SQL. See search-criteria/README.md.

Where to go next