必须重写behaviors(),因默认仅提供最小可用功能,不校验动词合法性、不强制json输出、不拦截未授权请求;需显式配置contentnegotiator、verbfilter及jwtauth等行为以满足rest规范与微服务安全要求。

Yii RESTful 接口的行为(behaviors)不是可选装饰,而是决定接口是否真正符合 REST 规范、能否被外部系统稳定调用的核心配置。漏掉或写错 behaviors(),yii\rest\ActiveController 就只会返回原始模型数据,不处理内容协商、动词限制、认证钩子,甚至可能让 POST 请求绕过验证直接插入空记录。
为什么必须重写 behaviors() 而不是靠默认?
Yii 的 yii\rest\ActiveController 确实自带基础行为,但它们是“最小可用”而非“开箱即用”:默认不校验 HTTP 动词合法性,不强制 JSON 输出,不拦截未授权请求。真实微服务场景下,这些都必须显式声明。
-
ContentNegotiator行为确保只响应application/json,拒绝Accept: text/html这类非法请求头 -
VerbFilter行为把GET /users绑定到actionIndex(),同时阻止DELETE /users这种无意义操作(因为没实现) - 若启用 JWT 认证,
AuthMethod子类(如JwtAuth)也必须注册进 behaviors,否则Authorization头永远被忽略
常见 behaviors 配置陷阱与修正
最常出错的是复制粘贴示例代码后忽略上下文差异,比如:
- 直接照搬
['class' => 'yii\filters\auth\HttpBearerAuth'],但项目实际用的是 JWT 令牌而非 Basic Auth —— 应换为自定义的JwtAuth类 - 在
behaviors()中漏掉父类行为:return ArrayHelper::merge(parent::behaviors(), [...])才能保留RateLimiter等内置逻辑 - 把
ContentNegotiator的formats写成['text/html' => Response::FORMAT_HTML]—— RESTful API 不该支持 HTML 格式,必须限定为['application/json' => Response::FORMAT_JSON]
如何让 behaviors 支持多版本控制器复用?
当有 v1/UserController 和 v2/UserController 时,不要在每个控制器里重复写一模一样的 behaviors 数组。更可靠的做法是抽离为基类:
class RestController extends \yii\rest\ActiveController
{
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['contentNegotiator']['formats']['application/json'] = Response::FORMAT_JSON;
$behaviors['authenticator'] = [
'class' => JwtAuth::class,
'except' => ['options'], // OPTIONS 预检请求不鉴权
];
return $behaviors;
}
}
然后让 v1/UserController 和 v2/UserController 都继承这个 RestController。这样既能统一认证策略,又避免因版本迭代导致 behaviors 配置不一致。
真正难的不是写对 behaviors,而是在接口上线后,有人悄悄注释掉 VerbFilter 来“临时兼容旧客户端”,结果导致 PUT 请求被当成 GET 执行 —— 这类修改不会报错,但会破坏整个资源状态机,且极难定位。











