magdev da097051ca v0.2.0 (10/N): bridge:export console command + QML hook
PLAN.md §12 *Data backup / export* called for "a bridge:export console
command and a UI hook for backup-to-file from v1". Shipping both now
so the v0.2.0 surface has the data-portability story end-to-end:

PHP side — `bin/console bridge:export <destination>`:
- Reads the source path from DATABASE_URL so it works in dev mode
  (developer's source-tree var/data.sqlite) and bundled mode (user
  data dir SQLite) without environment-aware logic.
- SQLite-only by design (PLAN.md §6 — single-instance SQLite-first);
  emits a clear error for non-sqlite:// URLs rather than pretending
  to support drivers that need driver-specific dump tooling.
- Overwrites the destination if it exists (the FileDialog or shell
  redirect that produced the path has already confirmed).
- 4 unit tests: happy path, non-SQLite URL, missing source,
  overwrite. Test count 24 → 28.

QML side — Q_INVOKABLE BackendConnection.exportDatabase(path):
- Bundled mode only; dev mode emits databaseExportFailed and
  returns false (developers own their SQLite directly).
- Accepts both filesystem paths and `file://` URLs (FileDialog
  results).
- Returns synchronously with bool but also emits async signals
  databaseExported(dst) / databaseExportFailed(reason) so QML
  can drive a snackbar / log without polling the return value.
- Removes any existing destination first (QFile::copy refuses
  to overwrite); the picker has already confirmed the choice.

Drive-by: parse_url() rejects sqlite:///abs/path on PHP 8.5+ (the
host-less triple-slash trips its strictness). Switched to a
prefix-strip — Doctrine DBAL only emits two URL shapes for
SQLite anyway (sqlite:///abs and sqlite://relative).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 20:36:51 +02:00

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 04a are merged (working framework, real POC, Linux AppImage, auto-update, release CI). macOS and Windows packaging are deferred to 4b/4c. See 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

git clone https://src.bundespruefstelle.ch/magdev/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:

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/.

Documentation

The full developer documentation lives under docs/:

Design rationale and roadmap live in PLAN.md. User-facing changes per release are in 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.

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 VersioningMAJOR.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.

Description
Bridge to run Symfony applications with native QML interfaces
Readme 503 KiB
v0.1.0 Latest
2026-05-03 10:21:14 +00:00
Languages
PHP 44.4%
C++ 34.4%
Shell 10.3%
QML 8.1%
CMake 1.4%
Other 1.4%