README is now tight and link-heavy: 60-second tour, then deep links into docs/. The wall of detail moved out. docs/ covers the framework end-to-end: - getting-started.md — prerequisites by distro (Tumbleweed, Fedora, Debian/Ubuntu, Arch), full first-run walkthrough, troubleshooting. - architecture.md — process pair, transport, dev/bundled mode. - update-semantics.md — state machine + optimistic mutations + key round-tripping. - reactive-models.md — ReactiveListModel, ReactiveObject, Mercure dual-publish. - makers.md — make:bridge:resource/command/window. - dev-workflow.md — hot reload (PHP + QML), dev console, editor configs, bridge:doctor, snapshot/integration test loops, perfsmoke. - bundled-mode.md — supervisor, per-session secret rotation, first-launch migrations, auto-update wiring. - packaging-linux.md — make appimage, build-appimage.sh CLI, AppImageUpdate sidecar, perfsmoke budgets, release CI, bundle-size breakdown. - qml-api.md / php-api.md — exhaustive symbol reference with all Q_PROPERTY/Q_INVOKABLE/signals + every public PHP service / attribute / command. - configuration.md — every env var (host, Symfony, dev script, packaging script, perfsmoke), every CLI flag (php-qml-init, build-appimage.sh), make targets, default ports/paths. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
94 lines
4.4 KiB
Markdown
94 lines
4.4 KiB
Markdown
# php-qml
|
||
|
||
A framework for native desktop applications with a **Symfony / FrankenPHP** backend and a **Qt / QML** frontend, packaged as a single distributable per OS.
|
||
|
||
> **Status:** Phase 5 / pre-v0.1.0. Phases 0–4a are merged (working framework, real POC, Linux AppImage, auto-update, release CI). macOS and Windows packaging are deferred to 4b/4c. See [CHANGELOG.md](CHANGELOG.md).
|
||
|
||
---
|
||
|
||
## What it is
|
||
|
||
php-qml lets a PHP developer write a desktop app using ordinary Symfony on the backend and ordinary QML on the frontend. The two halves run as a **process pair** inside one bundled binary:
|
||
|
||
- A Qt/QML host owns the window, input, and rendering.
|
||
- A bundled FrankenPHP child runs a Symfony app in worker mode.
|
||
- They communicate over a local socket — HTTP for commands and queries, Mercure SSE for state push.
|
||
|
||
It is **not** a PHP↔Qt language binding — the languages run in separate processes; the bridge is a wire protocol, not an FFI layer. That deliberately avoids the failure mode that left php-gtk and php-qt unmaintained.
|
||
|
||
## 60-second tour
|
||
|
||
```bash
|
||
git clone https://gitea.example/<you>/php-qml && cd php-qml
|
||
|
||
# Scaffold a fresh app
|
||
./bin/php-qml-init my-app
|
||
|
||
# Run it
|
||
cd my-app
|
||
make doctor # readiness check
|
||
make dev # FrankenPHP --watch + Qt host
|
||
```
|
||
|
||
Add a reactive resource (entity + REST controller + QML snippet) with one maker:
|
||
|
||
```bash
|
||
cd my-app/symfony
|
||
bin/console make:bridge:resource Todo
|
||
bin/console make:migration && bin/console doctrine:migrations:migrate -n
|
||
```
|
||
|
||
`make dev` opens the Qt window, connection state flips to **Online**, and the generated `TodoList.qml` shows a list whose `ReactiveListModel` is auto-subscribed to `app://model/todo` over Mercure. There is no handwritten cross-side glue.
|
||
|
||
For a non-trivial app with a multi-window test, crash-recovery test, and AppImage packaging, see [`examples/todo/`](examples/todo/README.md).
|
||
|
||
## Documentation
|
||
|
||
The full developer documentation lives under [`docs/`](docs/README.md):
|
||
|
||
- **[Getting started](docs/getting-started.md)** — prerequisites by distro, first project, troubleshooting.
|
||
- **[Architecture](docs/architecture.md)** — process pair, transport, dev vs bundled mode.
|
||
- **[Update semantics](docs/update-semantics.md)** — connection state machine, optimistic mutations, idempotency.
|
||
- **[Reactive models](docs/reactive-models.md)** — `ReactiveListModel`, `ReactiveObject`, Mercure dual-publish.
|
||
- **[Makers](docs/makers.md)** — `make:bridge:resource` / `command` / `window`.
|
||
- **[Dev workflow](docs/dev-workflow.md)** — hot reload, dev console, editor setup, `bridge:doctor`.
|
||
- **[Bundled mode](docs/bundled-mode.md)** — supervisor, per-session secret rotation, first-launch migrations.
|
||
- **[Linux packaging](docs/packaging-linux.md)** — `make appimage`, auto-update, performance budgets.
|
||
- **[Configuration reference](docs/configuration.md)** — env vars, CLI flags.
|
||
- **[QML API reference](docs/qml-api.md)** / **[PHP API reference](docs/php-api.md)** — singletons, components, attributes, services.
|
||
|
||
Design rationale and roadmap live in [PLAN.md](PLAN.md). User-facing changes per release are in [CHANGELOG.md](CHANGELOG.md).
|
||
|
||
## Tech stack
|
||
|
||
PHP 8.4+ · Symfony 8 · Doctrine ORM 3 · FrankenPHP 1.12+ (worker mode) · Mercure · Qt 6.5+ · CMake · Composer · Gitea Actions
|
||
|
||
## Roadmap
|
||
|
||
- **Phase 0** ✅ throwaway transport spike.
|
||
- **Phase 1** ✅ framework skeleton, dev mode, single-instance lock, CI quality gate.
|
||
- **Phase 2** ✅ reactive models, update semantics, headline maker.
|
||
- **Phase 3** ✅ POC todo app, integration + snapshot tests.
|
||
- **Phase 4a** ✅ bundled mode, Linux AppImage, release CI, AppImageUpdate.
|
||
- **Phase 4b/4c** ⏳ macOS / Windows packaging.
|
||
- **Phase 5** 🚧 DX polish — dev console, init script, hot-reload docs, v0.1.0 prep.
|
||
|
||
## Contributing
|
||
|
||
Active development happens on the `dev` branch; `main` only carries release commits. Pull requests target `dev`.
|
||
|
||
```bash
|
||
cd framework/php && composer quality # PHPStan + cs-fixer + PHPUnit
|
||
cd examples/todo && make quality # adds qmllint + integration test
|
||
```
|
||
|
||
A dedicated `CONTRIBUTING.md` arrives with Phase 5's wrap-up.
|
||
|
||
## Versioning
|
||
|
||
[Semantic Versioning](https://semver.org/) — `MAJOR.MINOR.BUGFIX`. Pre-v1.0.0, minor bumps may break public API.
|
||
|
||
## License
|
||
|
||
To be decided before v0.1.0 is tagged. The framework's own code will be permissively licensed; Qt is shipped under LGPL with relinkability obligations — see [PLAN.md §12](PLAN.md#12-open-questions-and-risks).
|