10: Tooling & CLI

Phlo apps have a CLI layer for build, lint, release and reflection. Always use it through the app's dev entrypoint.

10.1: Build commands

php www/app.php build::run
php www/app.php build::lint
php www/app.php build::release
php www/app.php build::config
php www/app.php build::changed

build::lint should return an empty array:

[]

If lint reports errors, fix the .phlo source and build again. Never patch the generated PHP.

10.2: Reflect commands

Reflection helps you understand an app before you change it:

php www/app.php reflect::context
php www/app.php reflect::compactRoutes
php www/app.php reflect::compactViews
php www/app.php reflect::resourceSummary
php www/app.php reflect::objectIndex
php www/app.php reflect::functionIndex

These commands return JSON and are intended for development environments with build: true.

The same introspection drives the Graph view of the Phlo Control Center: every class, resource and dependency edge of your app, rendered live from reflect::graph:

The Control Center Graph view: your app's classes, resources and dependency edges, rendered live from reflect::graph

10.3: General CLI dispatch

build:: and reflect:: are just two examples of a more general mechanism. Phlo's CLI can call any static, method or function in your app:

php www/app.php tasks::run                   # static method on a class
php www/app.php app.heartbeat                # method on a Phlo instance
php www/app.php answer "is an eel a fish"   # global function

Three patterns:

Pattern Dispatch Example
Class::method args Static method on the class tasks::run, backup::nightly
object.method args Instance method via phlo(object) app.heartbeat, cms.reindex
function args Global function answer "question"

Output goes to stdout as JSON, errors go to stderr with a non-zero exit code. That makes every routine in your app directly usable from cron, deploy scripts, monitoring or a terminal, without building a separate CLI layer for it.

Only available with build: true in www/app.php. Do not run against a live production environment.

10.4: Debug helpers

With debug: true in phlo_app(...), Phlo activates a set of helpers for inspection during dev. In production they are inert.

Helper Purpose Behavior
d(...$args) Dump values into the response, continue running Collected in %res->dump; rendered to the browser console at the end of the request. Inert without debug: true
dx(...$args) Dump + STOP Sync: full debug page with the source-mapped .phlo file and line. Async/CLI/streaming: the dump arrives in the browser console via the apply payload. Worker-safe: throws instead of calling die()
debug($msg) Append a line to the debug log; debug() without arguments returns everything collected Logged to the browser console with the request stats
error($msg, $code = 500) Runtime error for the Phlo exception handler Throws a PhloException, logged in data/errors.json
trace($node, $args) Manual trace event (only active with trace: true) Adds an event to the trace log, see the Trace chapter

The lifecycle: helpers collect during the request (%res->dump, %res->debug); at the end of a sync page an inline script logs everything to the browser console together with memory, duration and trace metadata, and async responses carry the same data in their apply payload. Objects are unwrapped via objInfo(). Runtime errors accumulate in data/errors.json (message, source-mapped file and line, count, last occurrence); read them with reflect::errors or in the Phlo Control Center.

method buildReport {
    $data = $this->load
    debug('loaded', count: count($data))
    if (!$data) error('No data to report')
    dx($data[0])
}

dx() is your primary "stop and look at what's there" tool during development. Forgot a dx() in code that ships to release? In debug: false mode it behaves just like error(), no silent passthrough.

10.5: Workflow

In a dev environment the Phlo Control Center (at /phlo) puts this whole loop in the browser: source, build, release and errors, with every file one click away:

The Phlo Control Center source view: every .phlo file highlighted and searchable, one click from build, release and errors

  1. Read the source and the reflection output first.
  2. Only modify .phlo, data/app.json or entrypoints.
  3. Run build::run.
  4. Run build::lint.
  5. Test the relevant HTTP routes.
  6. Run build::release when the stage/release output needs updating.

10.6: Dev, stage and production

Dev typically has:

auth: true,
build: true,
debug: true,

In build+debug mode, the built-in control UI lives at /phlo by default; use control: 'path' in phlo_app(...) to pick a different path. Stage/production typically runs without build and without debug. The webroot points to release/www/.

10.7: HEAD and async

The current runtime supports the normal HTTP methods, including HEAD. Async requests are handled by the frontend resource and use the same routes as sync requests, unless you explicitly declare a route otherwise.

We use essential cookies to make this site work. With your permission we also use analytics to improve the site.