Esc
Directory Structure
ZealPHP projects follow a predictable layout so that the runtime can discover routes, APIs, templates, and task handlers without additional configuration. This guide explains what each top-level directory does, when it is loaded, and how it participates in the server lifecycle.
zealphp/
├── app.php
├── api/
├── public/
├── route/
├── template/
├── task/
├── src/
├── ext/
├── tests/
├── examples/
├── scripts/
├── deploy/
├── vendor/
├── docs/
└── ...
Entrypoint
app.php– Boots ZealPHP by callingApp::init(), wiring middleware, and invokingApp::run(). It is the only script that should start the OpenSwoole HTTP server. Keep orchestration logic here; do not dispatch routes inline.
HTTP Surface
public/– ZealPHP's document root (the ApacheDocumentRootequivalent): the directory every implicit route and the built-in static handler resolve against. It defaults topublic/— override it withApp::documentRoot('…')beforeApp::init()(see routing.md). Contains PHP scripts and assets served via implicit routing: a request to/foo/barresolves topublic/foo/bar.php(without requiring.phpin the URL). Index files are handled automatically (public/index.php,public/foo/index.php). Use this directory for traditional PHP pages, SPA bootstraps, or static fallbacks.route/– Optional route injection point. All files in this directory are included before implicit routes are registered, allowing teams to register additional explicit routes without editingapp.php. Each file typically calls$app = App::instance();followed by$app->route(...),nsRoute(...), orpatternRoute(...).api/– Implicit API router. Files insideapi/become callable via/api/<path>. Subdirectories map to namespaces:api/device/list.phpis accessible as/api/device/list. Each file returns a closure stored in a variable whose name matches the file base name;ZealAPIbinds that closure into the API context at runtime.template/– Houses reusable view fragments loaded viaApp::render(). The default template root istemplate/;App::render()may descend into a subdirectory (e.g.template/home/) when the current page name matches one. Keep presentation-only PHP here to support dynamic HTML streaming.
Background Execution
task/– Contains task worker handlers triggered via$server->task(). Long-running, blocking work can also be offloaded to a child process viacoproc()when running in superglobals mode. Each file exposes a closure identified by file name (e.g.,task/backup.phpdefines$backup).examples/– Not loaded automatically, but offers reference scripts for coroutines, prefork processing, and stream wrappers. Use these as templates when experimenting with concurrency features.
Framework Core
-
src/– Framework source code. Important highlights:App.php– The main server class responsible for routing, middleware orchestration, template rendering, and OpenSwoole integration.RequestContext.php– The per-request state container that virtualizes PHP superglobals ($g->get/post/cookie/server/session/…). Per-coroutine in coroutine mode, process-wide singleton in sync superglobals modes.G.php– A backward-compatibility shim:requiresRequestContext.phpandclass_aliasesG→RequestContext(the legacyG::instance()name still works).HTTP/– Request and response wrappers that provide durable hooks for ZealPHP features while exposing the underlying OpenSwoole objects when needed.Session/– Session managers that bridge traditional PHP session semantics with OpenSwoole’s coroutine context.utils.php– Helper functions:coproc()(background-process spawner), logging utilities (elog(),zlog(),access_log()), and stack-trace helpers (jTraceEx()).
-
vendor/– Composer-managed dependencies and autoload metadata. Do not edit manually.
Extensions and Testing
ext/– C source for ext-zealphp (ext/zealphp/), the optional PHP extension that provides per-coroutine isolation of superglobals,$GLOBALS, function statics,require_oncere-execution, and per-request class/function-static resets. Built withphpize && ./configure && make. Required forApp::mode(App::MODE_COROUTINE_LEGACY). Install viapie install zealphp/extorsudo bash setup.sh.tests/– PHPUnit 11 test suite.tests/Unit/runs without a server;tests/Integration/requiresphp app.phpon:8080(orZEALPHP_TEST_PORT). Run with./vendor/bin/phpunit --testdox. See CLAUDE.md for the full testing matrix.
Scripts and Deployment
scripts/– Helper shell scripts:bench.sh(local performance sweep),zealphp.sh(optional higher-level CLI wrapper), and CI utilities.deploy/– Deployment artifacts:zealphp.service(systemd unit template,Type=simple, no-dflag) and other server-configuration examples.
Documentation and Meta
docs/– The documentation set you are currently reading. Treat these Markdown files as publishable artifacts.README.md,CHANGELOG.md,TODO.md– Repository-level guidance, release history, and future work items.setup.sh– Bootstrap script that installs OpenSwoole, ext-zealphp (with uopz as a fallback), and Composer dependencies. Useful for setting up CI or fresh workstations.
What Gets Loaded at Runtime?
app.phpinitializesZealPHP\App.- All files under
route/are included so they can register explicit routes. - Implicit routes are registered for:
/and public directory traversal/api/*endpoints.phppattern guards (403 when direct PHP execution is disabled)
- Middleware and session managers are wired.
- OpenSwoole server starts listening and the request lifecycle begins.
Understanding this flow makes it easy to decide where a new feature belongs:
- Need a new API? Add
api/<module>/<action>.php. - Need to override routing or apply authentication? Drop a file in
route/. - Need a view fragment? Create it under
template/. - Need an async job or background worker? Add a closure in
task/and dispatch via$server->task()orcoproc().