Yii2 REST API仅GET方法可用,其余请求返回404错误
我之前也踩过一模一样的坑!Yii2的REST API配置里有几个很容易忽略的点,导致除了GET之外的请求都返回404,甚至连JSON格式的错误提示都没有。结合你给出的EmployeeController继承ActiveController的代码,咱们一步步排查:
1. 先确认URL路由配置是否到位
Yii2的REST路由不是自动生效的,必须在配置文件里手动添加规则。你需要打开config/web.php(后台项目则是config/main.php),找到urlManager配置,确保里面包含REST的路由规则:
'urlManager' => [ 'enablePrettyUrl' => true, 'enableStrictParsing' => true, 'showScriptName' => false, 'rules' => [ // 关键:添加REST路由规则 ['class' => 'yii\rest\UrlRule', 'controller' => 'employee'], // 其他项目路由... ], ],
这里要注意两个细节:
enableStrictParsing如果设为true,所有请求必须能匹配到规则,否则直接返回404controller参数要和你的控制器名完全对应(这里是employee,对应EmployeeController)
2. 检查CSRF验证是否拦截了请求
Yii2默认对POST/PUT/DELETE这类修改型请求会做CSRF验证,如果你的API是给第三方调用的(没有前端页面的CSRF token),必须关闭这个验证,否则请求会被拦截,有时候就表现为404(因为验证失败后没有走REST的错误处理流程)。
方法一:在控制器里单独关闭
直接在EmployeeController里添加behaviors方法:
public function behaviors() { $behaviors = parent::behaviors(); // 移除CSRF验证 unset($behaviors['authenticator']['csrfValidation']); return $behaviors; }
方法二:全局针对API路由关闭
如果有多个API控制器,也可以在config/web.php的request配置里做全局处理:
'request' => [ 'enableCsrfValidation' => true, 'csrfParam' => '_csrf-frontend', // 针对employee开头的API路由关闭CSRF 'enableCsrfValidation' => !Yii::$app->request->isAjax && !preg_match('/^\/employee/', Yii::$app->request->pathInfo), ],
3. 确认你的请求方式和URL是否正确
Yii2 REST的标准请求规则要记清楚,别搞混了:
- 创建员工:
POST请求到http://dev.exp-yii.com/employee - 更新单个员工:
PUT请求到http://dev.exp-yii.com/employee/1(1是员工ID) - 删除单个员工:
DELETE请求到http://dev.exp-yii.com/employee/1 - 获取单个员工详情:
GET请求到http://dev.exp-yii.com/employee/1
如果你的请求URL或者HTTP方法不对(比如用POST请求单个员工的URL),就会直接返回404。
4. 检查服务器是否支持PUT/DELETE等HTTP方法
有些服务器默认禁用了PUT/DELETE这类非标准方法,这时候需要配置服务器:
Apache环境(配置.htaccess)
确保项目根目录的.htaccess有这些内容,保证所有请求都转发到Yii2的入口文件:
RewriteEngine on # 如果是真实存在的文件或目录,直接访问 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d # 否则转发到index.php处理 RewriteRule . index.php
另外还要确认Apache已经启用了mod_rewrite模块。
Nginx环境(配置server块)
在Nginx的server配置里添加这段,确保路由能被Yii2正确解析:
location / { try_files $uri $uri/ /index.php$is_args$args; }
5. 确认模型的主键配置正确
ActiveController依赖模型的主键来定位单个资源,如果你的Employee模型主键不是默认的id,必须在模型里重写primaryKey()方法:
class Employee extends \yii\db\ActiveRecord { public static function primaryKey() { return ['your_primary_key_column']; // 替换成你实际的主键字段 } // 其他模型代码... }
如果主键配置错误,更新/删除请求会找不到对应的资源,自然返回404。
按照这个顺序排查,基本就能解决问题啦!
内容的提问来源于stack exchange,提问作者Praneeth Nidarshan

