ThinkPHP 8 Best Practices for API Development
This document serves as a guide for developing APIs within the Stooland project using ThinkPHP 8. It outlines standard practices to ensure consistency, maintainability, and proper debugging capabilities.
1. Logging
Do NOT use: error_log(), var_dump(), print_r()USE: think\facade\Log
Using the framework's logging facade ensures that logs are correctly routed, formatted, and stored in the runtime directory (runtime/log/), making them accessible for debugging and monitoring.
Usage Examples
use think\facade\Log;
// Info level (General flow, key events)
Log::info('[ModuleName] Action started with params: ' . json_encode($params));
// Error level (Exceptions, critical failures)
Log::error('[ModuleName] Failed to process request: ' . $exception->getMessage());
// Debug level (Detailed data for troubleshooting - ensure this is not too verbose in production)
Log::debug('[ModuleName] API Response: ' . $rawResponse);Contextual Logging
Always include a prefix or context identifier (e.g., [VolcengineLLM]) to make it easier to filter logs.
Log::info("[VolcengineLLM] ImageGen Req: URL={$url}, Key={$maskKey}");2. Request Handling
Do NOT use: $_GET, $_POST, $_REQUESTUSE: $this->request or $this->getParams() (if extending ApiBaseController)
Getting Parameters
// In a controller extending ApiBaseController
$params = $this->getParams(); // Get all params
$specific = $this->getParams('key', 'default_value'); // Get specific param with defaultInput Validation
Always validate input before processing.
if (empty($params['req_key'])) {
return $this->sendResponse(ERROR_LOGIC, [], 'Missing required parameter: req_key');
}3. Response Formatting
Do NOT use: json_encode(), echo, dieUSE: $this->sendResponse() (if extending ApiBaseController)
Standardizing responses ensures frontend clients can consistently parse success and error states.
// Success
return $this->sendResponse(0, $data);
// Error with custom message
return $this->sendResponse(ERROR_LOGIC, [], 'Something went wrong');4. Exception Handling
Wrap logic in try-catch blocks to prevent unhandled exceptions from exposing stack traces to the client (unless in debug mode) and to provide meaningful error messages.
try {
// Business logic
} catch (\Throwable $e) {
Log::error('[ModuleName] Exception: ' . $e->getMessage());
return $this->sendResponse(ERROR_LOGIC, [], 'Operation failed: ' . $e->getMessage());
}5. Service Layer
Keep controllers thin. Business logic should reside in Service classes.
- Controllers: Handle HTTP request parsing, validation, and response formatting.
- Services: Implement the actual business logic, database interactions, and external API calls.
6. Configuration & Environment
Do NOT use: Hardcoded credentials USE: .env file and Env::get()
use think\facade\Env;
$apiKey = Env::get('VOLCENGINE.ARK_KEY');This document is a living guide. Please update it as new patterns or standards are adopted.