Title here
Summary here
All business logic in a Pionia app lives in services — PHP classes with one method per action. Pionia Shop clients POST JSON to http://127.0.0.1:8000/api/v1/:
{ "service": "product", "action": "list" }You finished Pionia Shop tutorial Step 1 and want to design Pionia Shop’s Moonlight API — services, actions, validation, and optional generic CRUD for task, member, and project.
{ "service", "action" } maps to PHP classes and *Action methods/docsflowchart LR POST["POST /api/v1/"] --> Switch[MainSwitch] Switch --> Task["task → ProductService"] Switch --> Member["member → CustomerService"] Switch --> Project["project → OrderService"] Task --> Action["listAction / createAction"]
| Topic | Page |
|---|---|
| Architecture overview | Moonlight overview |
| Your first service | Services |
| Action methods | Actions |
| Input rules | Validation |
| CRUD without boilerplate | Generic services |
In the Pionia Shop tutorial you build:
| Service | Purpose |
|---|---|
task | List, create, and assign tasks |
member | Login and team profiles |
project | Group tasks by client project |
/api/v2/@moonlight-* and OpenAPIEvery response uses the same envelope: returnCode, returnMessage, returnData. See Requests & responses.
service and action.ProductService is not enough; add 'task' => ProductService::class in MainSwitch::registerServices().ProductService manual when assignee logic grows; use OrderService as generic CRUD first.PORT in environment/.env), not 3000 or 8003.Register task, member, and project.
Continue Pionia Shop tutorial hands-on.
422 errors when title is missing.