Yii2 POST参数映射

7
我有一些发送类似数据的JS脚本:
    $.ajax({
        type: "POST",
        url: '/manage/add-shops/',
        data: {'id':id, 'shops': shops}

'shops' 是一个包含约1000个元素的数组,因此我需要通过POST发送它。 我有一个yii2控制器方法:

class ManageController extends Controller {
    public function actionAddShops($id, $shops=array()) {
       ....
    }

路由没问题,但我收到了以下错误信息:
"Missing required parameters: id"

看起来POST参数没有映射到方法参数。谢谢。

6个回答

8
你说得对,出于某些原因,Yii2只自动绑定GET变量,但不幸的是没有POST。
然而,你可以轻松地进行魔法绑定;你所要做的就是重写控制器的runAction()函数。如果你不想为每个控制器手动执行此操作,只需创建一个基本控制器,并在需要时从它继承。请检查以下代码片段:
public function runAction($id, $params = [])
{
    // Extract the params from the request and bind them to params
    $params = \yii\helpers\BaseArrayHelper::merge(Yii::$app->getRequest()->getBodyParams(), $params);
    return parent::runAction($id, $params);
}

那么你就可以在控制器操作中正常访问$id$shops,就像在Yii1中一样。

希望这能帮到你。


2

所以,没有本地的POST映射,但是我们可以像这样实现它:

class OurUrlRule extends UrlRule implements UrlRuleInterface {
    public function parseRequest($manager, $request, $add_post = true, $add_files = true) {
        $result = parent::parseRequest($manager, $request);
        if($result !== false) {
            list($route, $params) = $result;
            if($add_post    === true) {
                $params = array_merge($params,$_POST);
            }
            if($add_files   === true) {
                $params = array_merge($params,$_FILES);
            }
            return [$route, $params];
        }
        return false;
    }
}

然后,将其添加到路由中:

['pattern'=>'manage/<action:\S+>', 'route'=>'manage/<action>', 'suffix'=>'/', 'class' => 'app\components\OurUrlRule',]

抱歉,但这是完全错误的。Yii一直实现了POST映射,并且仍然如此。请参见此处http://www.yiiframework.com/doc-2.0/yii-web-request.html#post%28%29-detail - Joe Miller
对不起,我犯了一个错误,我的意思是直接将POST映射到被调用的方法。 - arkhamvm
我现在明白你的意思了。那么,调用一个单独的函数并将帖子数据作为方法参数传递如何?这可以实现你想要的效果。 - Joe Miller

1

只需在您的控制器中添加:

public function bindActionParams($action, $params)
{
    return array_merge($params, Yii::$app->getRequest()->getBodyParams());
}

actionAddShops将从POST请求中接收$id和$shops参数。


-1
当您将参数传递给控制器操作时,只有在它们位于URL的GET中时才可用。如果您通过POST发送参数,则需要通过Yii::$app->request->post方法访问它们。
因此,您的函数最终看起来像这样;
enter class ManageController extends Controller {
public function actionAddShops() {
   $post = Yii::$app->request->post();
   $id = $post['id'];
   $shops = $post['shops'];
}

1
这正是我想要避免的。 - arkhamvm
我可以问一下为什么您想要避免这样做吗?在我看来,这是将数据传递给控制器的最有效方式。 - Joe Miller
因为编写 function actionAny($i,$j,$k) 比编写 function actionAny() { $post = Yii::$app->request->post(); if(!isset($post['i'] === null) { return false; } else {$i = $post['i'];} 等等更加简单易懂。 - arkhamvm
在这种情况下,@Arkham.vm,你的答案是否定的。Yii只从url的GET部分映射操作参数。除非您自己编写类似于下面的函数,否则无法使用POST数据。不过,我可以建议,如果您的操作需要如此详细的了解数据的排列方式,那么最好将一些功能委托给模型,而不是留给控制器。 - Joe Miller

-2
class ManageController extends Controller {
    public function actionAddShops() {
       var_dump($_POST);
    }

给你。


有自动的POST映射吗? - arkhamvm
您可以使用JSON代替POST。 - Vick
这对于JS脚本来说没问题,但如果它是一个标准的POST <form>呢? - arkhamvm
输入的 name 参数将是 $_POST 数组的键。例如,如果 name="foo",则 $_POST['foo'] 将包含该值。如果 Name = "foo[bar]",则 $_POST["foo"]["bar"] == value。 - Vick
你能澄清一下当你说映射时是什么意思吗?可以用俄语吗? - Vick
显示剩余2条评论

-2
$.ajax({
    type: "POST",
    url: '/manage/add-shops/',
    data: {'id':id, 'shops': shops}

class ManageController extends Controller {
public function actionAddShops($id, $shops=array()) {
   ....
}

从您的代码中我所理解的是,您正在使用POST方法通过ajax传递值,但如果您在控制器中使用带参数的操作方法,则意味着此操作需要使用GET方法。因此,只需将您的ajax方法更改为

$.ajax({
    type: "GET",
    url: '/manage/add-shops/',
    data: {'id':id, 'shops': shops}

然后检查它是否能够完美运行。


海报上说,“商店”可能是一个包含约1000个值的数组,因此不适合通过GET发送。 - Joe Miller
我能理解,但根据他的控制器,我已经修改了代码。 - Neeraj Kumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接