webman Framework Development
webman is a high-performance, long-lived in-memory PHP framework built on
workerman. Unlike PHP-FPM (bootstrap per request,
tear down after response), correct webman code starts from understanding the
resident-process model.
Core Mental Model: Resident Memory
After startup, a worker stays in memory and handles thousands of requests.
Hard rules that follow:
- Never
exit / die: they kill the whole worker and drop every
connection on that process.
- Static properties / globals survive across requests: data written by the
previous request can "leak" into the next. Keep request-scoped data in local
variables,
$request attributes, or support\Context under coroutines.
- Singletons are shared across requests: do not store request state on
singletons; array properties that only grow are memory leaks.
- Code changes need reload/restart (
php start.php reload). In debug
mode, status / connections help diagnose issues.
- Controllers are new per request by default (
controller_reuse => false
in config/app.php). If reuse is enabled, controller properties also
survive across requests.
Project Layout
├── app/ # Application code
│ ├── controller/ # Controllers (optional; MVC or DDD as you prefer)
│ ├── model/ # Models
│ ├── middleware/ # Middleware
│ └── functions.php # Custom helpers
├── config/ # All configuration
│ ├── route.php # Routes
│ ├── process.php # Process definitions (HTTP, custom, timers)
│ ├── middleware.php # Middleware registration
│ ├── database.php # Database (illuminate/database)
│ ├── redis.php # Redis
│ └── plugin/ # Plugin config
├── plugin/ # Application plugins
├── public/ # Static assets (only web-accessible directory)
├── process/ # Custom process classes
├── support/ # Framework bridge code
└── start.php # Entry point
Common Commands
composer create-project workerman/webman # create project
# Linux / macOS
php start.php start # foreground (debug)
php start.php start -d # daemon (production)
php start.php reload # graceful reload (code updates, keep connections)
php start.php restart -d # full restart (required after process.php, Timer, or resident data changes)
php start.php stop
php start.php status # process memory, request counts
php start.php connections # connection info
# Windows (no daemon / reload)
php windows.php
reload vs restart: reload only reloads app code (app/ and most of
config/). Changes to config/process.php or timers/connections already
created in onWorkerStart are not reloaded — use restart.
Coding Conventions
- PHP >= 8.0 (webman v2 requires 8.1+); always
declare(strict_types=1).
- Controller signatures:
public function action(Request $request): Response,
with support\Request.
- Return
Webman\Http\Response via helpers (response(), json(), view(),
redirect(), …). Do not echo.
- Prefer
illuminate/database (Db::table() / Eloquent models extending
support\Model).
- Read config with
config('app.debug'); never include config files.
- Log with
support\Log (Log::info() / Log::channel('xx')->info()), not
error_log or echo.
Do / Don't Cheatsheet
| Don't |
Do |
exit() / die() to end a request |
return response(...) or throw |
$_GET / $_POST / $_SESSION |
$request->get() / $request->post() / $request->session() |
header() / setcookie() |
$response->header() / $response->cookie() |
| Unbounded static arrays |
Bounded cache (LRU) or Redis |
| Request data on singletons |
Locals / support\Context (coroutines) |
| Timers created per request in app code |
Custom process in config/process.php |
| Static vars for request state under coroutines |
support\Context::set() / get() |
References (read on demand)
- Routing, controllers, request/response APIs: references/routing-controller.md
- Middleware (onion model, CORS, auth): references/middleware.md
- Database, Redis, cache, pagination, transactions: references/database-redis.md
- Custom processes, WebSocket/TCP, timers: references/custom-process.md
- Coroutines (webman v2), Context, concurrency, pools: references/coroutine.md
- Lifecycle, memory leaks, prevention: references/memory-lifecycle.md
- Plugin development (library vs app plugins): references/plugin.md
1---2name: webman3description: Expert skill for the webman framework (a long-lived, in-memory PHP framework based on workerman). Covers routing, controllers, middleware, database/Redis, custom processes, timers, coroutines (v2), plugin development, and guarding against memory leaks and cross-request state pollution under the resident process model. Use when the project has start.php, config/process.php, or support/bootstrap.php, or when the user mentions webman, workerman, 常驻内存 PHP, 协程 PHP, or long-lived/in-memory PHP.4---56# webman Framework Development78webman is a high-performance, long-lived in-memory PHP framework built on9[workerman](https://www.workerman.net/). Unlike PHP-FPM (bootstrap per request,10tear down after response), correct webman code starts from understanding the11resident-process model.1213## Core Mental Model: Resident Memory1415After startup, a worker stays in memory and handles thousands of requests.16Hard rules that follow:17181. **Never `exit` / `die`**: they kill the whole worker and drop every19 connection on that process.202. **Static properties / globals survive across requests**: data written by the21 previous request can "leak" into the next. Keep request-scoped data in local22 variables, `$request` attributes, or `support\Context` under coroutines.233. **Singletons are shared across requests**: do not store request state on24 singletons; array properties that only grow are memory leaks.254. **Code changes need reload/restart** (`php start.php reload`). In debug26 mode, `status` / `connections` help diagnose issues.275. **Controllers are new per request by default** (`controller_reuse => false`28 in `config/app.php`). If reuse is enabled, controller properties also29 survive across requests.3031## Project Layout3233```34├── app/ # Application code35│ ├── controller/ # Controllers (optional; MVC or DDD as you prefer)36│ ├── model/ # Models37│ ├── middleware/ # Middleware38│ └── functions.php # Custom helpers39├── config/ # All configuration40│ ├── route.php # Routes41│ ├── process.php # Process definitions (HTTP, custom, timers)42│ ├── middleware.php # Middleware registration43│ ├── database.php # Database (illuminate/database)44│ ├── redis.php # Redis45│ └── plugin/ # Plugin config46├── plugin/ # Application plugins47├── public/ # Static assets (only web-accessible directory)48├── process/ # Custom process classes49├── support/ # Framework bridge code50└── start.php # Entry point51```5253## Common Commands5455```bash56composer create-project workerman/webman # create project5758# Linux / macOS59php start.php start # foreground (debug)60php start.php start -d # daemon (production)61php start.php reload # graceful reload (code updates, keep connections)62php start.php restart -d # full restart (required after process.php, Timer, or resident data changes)63php start.php stop64php start.php status # process memory, request counts65php start.php connections # connection info6667# Windows (no daemon / reload)68php windows.php69```7071**reload vs restart**: reload only reloads app code (`app/` and most of72`config/`). Changes to `config/process.php` or timers/connections already73created in `onWorkerStart` are not reloaded — use restart.7475## Coding Conventions7677- PHP >= 8.0 (webman v2 requires 8.1+); always `declare(strict_types=1)`.78- Controller signatures: `public function action(Request $request): Response`,79 with `support\Request`.80- Return `Webman\Http\Response` via helpers (`response()`, `json()`, `view()`,81 `redirect()`, …). Do not `echo`.82- Prefer `illuminate/database` (`Db::table()` / Eloquent models extending83 `support\Model`).84- Read config with `config('app.debug')`; never `include` config files.85- Log with `support\Log` (`Log::info()` / `Log::channel('xx')->info()`), not86 `error_log` or `echo`.8788## Do / Don't Cheatsheet8990| Don't | Do |91|---|---|92| `exit()` / `die()` to end a request | `return response(...)` or throw |93| `$_GET` / `$_POST` / `$_SESSION` | `$request->get()` / `$request->post()` / `$request->session()` |94| `header()` / `setcookie()` | `$response->header()` / `$response->cookie()` |95| Unbounded static arrays | Bounded cache (LRU) or Redis |96| Request data on singletons | Locals / `support\Context` (coroutines) |97| Timers created per request in app code | Custom process in `config/process.php` |98| Static vars for request state under coroutines | `support\Context::set()` / `get()` |99100## References (read on demand)101102- Routing, controllers, request/response APIs: [references/routing-controller.md](references/routing-controller.md)103- Middleware (onion model, CORS, auth): [references/middleware.md](references/middleware.md)104- Database, Redis, cache, pagination, transactions: [references/database-redis.md](references/database-redis.md)105- Custom processes, WebSocket/TCP, timers: [references/custom-process.md](references/custom-process.md)106- Coroutines (webman v2), Context, concurrency, pools: [references/coroutine.md](references/coroutine.md)107- Lifecycle, memory leaks, prevention: [references/memory-lifecycle.md](references/memory-lifecycle.md)108- Plugin development (library vs app plugins): [references/plugin.md](references/plugin.md)