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).
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 upgrade — db-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¶
architecture.md— bootstrap lifecycle, HTTP / data-service flow, DB layerdependency-injection.md— diconfig file structureasynchrony.md— never-block rulesscaffolding.md— skills for routine taskstroubleshooting.md— common errors + fixesglossary.md— every term in one page