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" }Who this is for
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.
What you will learn
- How
{ "service", "action" }maps to PHP classes and*Actionmethods - When to use hand-written services vs Generic services
- How to document actions for frontend teams at
/docs
Before you start
- Introduction — Pionia Shop scaffold and ping curl
- Moonlight overview — envelope and switch model
How it works
flowchart LR POST["POST /api/v1/"] --> Switch[MainSwitch] Switch --> Task["task → ProductService"] Switch --> Member["member → CustomerService"] Switch --> Project["project → OrderService"] Task --> Action["listAction / createAction"]
Start here
| Topic | Page |
|---|---|
| Architecture overview | Moonlight overview |
| Your first service | Services |
| Action methods | Actions |
| Input rules | Validation |
| CRUD without boilerplate | Generic services |
Pionia Shop 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 |
Reference
- API versioning — when Pionia Shop adds
/api/v2/ - Moonlight security model — auth at the switch layer
- Documenting your API —
@moonlight-*and OpenAPI
Every response uses the same envelope: returnCode, returnMessage, returnData. See Requests & responses.
Common mistakes
- Legacy uppercase JSON keys — Moonlight expects lowercase
serviceandaction. - Skipping switch registration — scaffolding
ProductServiceis not enough; add'task' => ProductService::classinMainSwitch::registerServices(). - Using generic services for complex rules — keep
ProductServicemanual when assignee logic grows; useOrderServiceas generic CRUD first. - Wrong dev port — Pionia Shop examples use 8000 (
PORTinenvironment/.env), not 3000 or 8003.
What’s next
Services
Register task, member, and project.
API tutorial
Continue Pionia Shop tutorial hands-on.
Validation
422 errors when title is missing.