【问题标题】:yii2 POST parameters mappingyii2 POST 参数映射
【发布时间】:2015-03-28 08:51:19
【问题描述】:

我有一些发送模拟数据的 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 参数没有映射到方法参数。 谢谢。

【问题讨论】:

    标签: php mapping yii2


    【解决方案1】:

    你是对的,由于某种原因,Yii2 只自动绑定 GET 变量,但不幸的是不绑定 POST。

    但是,您可以轻松地进行魔术绑定;您所要做的就是覆盖控制器的runAction()。如果您不想为每个控制器手动执行此操作,只需创建一个基本控制器并在需要时从它扩展。检查以下sn-p:

    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);
    }
    

    然后你就可以像以前在 Yii1 中那样在控制器操作中访问 $id$shops 了。

    希望这会有所帮助。

    【讨论】:

      【解决方案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 一直都在执行后期映射,并且会继续这样做。见这里yiiframework.com/doc-2.0/yii-web-request.html#post%28%29-detail
      • 对不起,我弄错了,我的意思是 POST 直接映射到被调用的方法。
      • 我明白你现在的意思了。那么如何使用作为方法参数传递的发布数据调用单独的函数呢?这可以实现你想要的。
      【解决方案3】:

      只需添加到您的控制器:

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

      actionAddShops 将从帖子正文中收到 $id 和 $shops。

      【讨论】:

        【解决方案4】:

        当您将参数传递给控制器​​操作时,这些参数仅在它们位于 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'];
        }
        

        【讨论】:

        • 这正是我想要避免的。
        • 请问您为什么要避免这样做?在我看来,这是将数据传输到控制器的最有效方式。
        • 因为写function actionAny($i,$j,$k)而不是function actionAny() { $post = Yii::$app-&gt;request-&gt;post(); if(!isset($post['i'] === null) { return false; } else {$i = $post['i'];}等等更简单...
        • 在这种情况下@Arkham.vm 你的答案是否定的。 Yii 只映射来自 url 的 GET 部分的动作参数。 Post 数据只能从 Yii::$app->request->post() 获得;除非您像下面那样滚动自己的功能。不过,我可以建议,如果您的操作需要如此详细地了解数据的排列方式,那么您最好将一些功能委托给模型,而不是将其留给控制器。
        【解决方案5】:
        class ManageController extends Controller {
            public function actionAddShops() {
               var_dump($_POST);
            }
        

        给你。

        【讨论】:

        • 有自动POST映射吗?
        • 您可以使用 JSON 代替 POST。
        • JS 脚本没问题,但如果是标准的 POST
        • 输入名称参数将是 $_POST 数组的键。例如,如果 name="foo",$_POST['foo'] 将包含该值。名称 = "foo[bar]", $_POST["foo"]["bar"] == 值。
        • 所以只能手动做,没有自动POST映射?
        【解决方案6】:
        $.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}
        

        然后检查它是否可以正常工作。

        【讨论】:

        • 发帖人说 'shops' 可能是一个包含约 1000 个值的数组,因此不适合通过 GET 发送。
        • 我可以理解,但根据他的控制器,我已经更改了代码。
        猜你喜欢
        • 1970-01-01
        • 2015-07-01
        • 2019-07-01
        • 1970-01-01
        • 2023-03-14
        • 1970-01-01
        • 1970-01-01
        • 2019-11-26
        • 1970-01-01
        相关资源
        最近更新 更多