【问题标题】:Posting JSON objects to Symfony 2将 JSON 对象发布到 Symfony 2
【发布时间】:2012-03-20 06:59:16
【问题描述】:

我正在使用 Symfony 2 开发一个项目,我构建了一个包来处理我的所有数据库服务,这些服务可以来回传递 JSON 数据。

我的问题/问题:

  • 是否可以直接发布 JSON 对象?目前,我通过给对象一个名称json={"key":"value"} 来欺骗我的ajax 调用的普通表单帖子,如果我不给它一个名称,我似乎无法从Symfony 请求对象$JSON = $request->request->get('json'); 获取数据

  • 我希望能够使用一个服务包来处理来自 AJAX 调用或普通 Symfony 表单的数据。目前我正在提交提交的 Symfony 表单,获取数据然后使用 JSON_ENCODE,我只是不知道如何将数据发布到我的服务控制器,它需要请求数据。

总结一下:

  • 我希望 Symfony 接受 JSON 帖子对象而不是表单。

  • 我想使用请求/响应在控制器之间传递 JSON 对象

如果我说这一切都错了,请随时告诉我!

【问题讨论】:

    标签: php ajax json symfony


    【解决方案1】:

    如果您想在控制器中检索在请求正文中作为标准 JSON 发送的数据,您可以执行类似以下操作:

    public function yourAction()
    {
        $params = array();
        $content = $this->get("request")->getContent();
        if (!empty($content))
        {
            $params = json_decode($content, true); // 2nd param to get as array
        }
    }
    

    现在$params 将是一个包含您的 JSON 数据的数组。删除json_decode()调用中的true参数值,得到stdClass对象。

    【讨论】:

    • 感谢您的回复。我实际上是这样在周末工作的: $JSON = file_get_contents("php://input");这样做有什么问题吗?
    • php://input 是一次性只读的。阅读内容后,除非您传递该数据,否则无法再次阅读。使用 Symfony2 Request 对象可确保您可以在需要时在请求期间再次获取数据,而无需传递您的 $JSON 变量。
    • 答案中有一个小错字。该函数需要请求参数:public function yourAction(Request $request)
    • @whistlergreg 没有问题! :-) 通过参数传入请求对象是可选的;您应该可以按照上面的代码将其排除在外并从容器中获取它,或者将其传入。请参阅 herehere 了解不同的变体。
    • 这个有一个问题:您不能将这样的请求绑定到表单。有办法吗?
    【解决方案2】:

    我编写了将内容作为数组获取的方法

    protected function getContentAsArray(Request $request){
        $content = $request->getContent();
    
        if(empty($content)){
            throw new BadRequestHttpException("Content is empty");
        }
    
        if(!Validator::isValidJsonString($content)){
            throw new BadRequestHttpException("Content is not a valid json");
        }
    
        return new ArrayCollection(json_decode($content, true));
    }
    

    而我使用这个方法如下图

    $content = $this->getContentAsArray($request);
    $category = new Category();
    $category->setTitle($content->get('title'));
    $category->setMetaTitle($content->get('meta_title'));
    

    【讨论】:

    • symfony 上默认存在验证器类?
    • 数组没有方法,兄弟。
    • ArrayCollection 是一个类。
    【解决方案3】:

    页面上的javascript:

    function submitPostForm(url, data) {
        var form                = document.createElement("form");
            form.action         = url;
            form.method         = 'POST';
            form.style.display  = 'none';
    
        //if (typeof data === 'object') {}
    
        for (var attr in data) {
            var param       = document.createElement("input");
                param.name  = attr;
                param.value = data[attr];
                param.type  = 'hidden';
            form.appendChild(param);
        }
    
        document.body.appendChild(form);
        form.submit();
    }
    

    在某些事件之后(比如点击“提交”):

    // products is now filled with a json array
    var products = jQuery('#spreadSheetWidget').spreadsheet('getProducts');
    var postData = {
    'action':   action,
    'products': products
    }
    submitPostForm(jQuery('#submitURLcreateorder').val(), postData);
    

    在控制器中:

       /**
        * @Route("/varelager/bestilling", name="_varelager_bestilling")
        * @Template()
        */
       public function bestillingAction(Request $request) {
           $products   = $request->request->get('products', null); // json-string
           $action     = $request->request->get('action', null);
    
           return $this->render(
               'VarelagerBundle:Varelager:bestilling.html.twig',
               array(
                   'postAction' => $action,
                   'products' => $products
               )
           );
       }
    

    在模板中(在我的例子中是 bestilling.html.twig):

      {% block resources %}
           {{ parent() }}
           <script type="text/javascript">
           jQuery(function(){
               //jQuery('#placeDateWidget').placedate();
               {% autoescape false %}
               {% if products %}
    
               jQuery('#spreadSheetWidget').spreadsheet({
                   enable_listitem_amount: 1,
                   products: {{products}}
               });
               jQuery('#spreadSheetWidget').spreadsheet('sumQuantities');
               {% endif %}
               {% endautoescape %}
    
           });
           </script>
       {% endblock %}
    

    Alrite,我想这就是你想要的 :)

    编辑 要在不模拟表单的情况下发送内容,您可以使用 jQuery.ajax()。 这是一个与上述精神相同的示例,它不会触发页面刷新。

    jQuery.ajax({
        url:        jQuery('#submitURLsaveorder').val(),
        data:       postData,
        success:    function(returnedData, textStatus, jqXHR ){
            jQuery('#spreadSheetWidget').spreadsheet('clear');
            window.alert("Bestillingen ble lagret");
            // consume returnedData here
    
        },
        error:      jQuery.varelager.ajaxError, // a method
        dataType:   'text',
        type:       'POST'
    });
    

    【讨论】:

    • 感谢您的快速响应!本质上,您仍在使用 javascript 提交普通表单,这就是我目前正在做的事情,我想知道是否可以在不模拟表单的情况下直接发布 JSON 对象,如果不是没有戏剧的话。另外,一旦我在 Symfony 中拥有 JSON 对象,是否可以将其作为 Request 对象发送到另一个服务?
    • 我在编辑中处理了您的评论。我不太确定如何在没有 jQuery 的情况下做 ajax 的事情,所以我把它留给你。要将某人发送到另一个控制器,您可以将他们重定向到那里。这在 RedirectingForwarding 下的 symfony.com/doc/2.0/book/controller.html 中进行了介绍。祝你好运!
    • 再次感谢您,我应该更清楚一点,我可以提交对象没有问题,我只是不知道如何在没有名称的控制器中检索它
    • $request->request->get('action', null) 当然等于 $request->request->get('action')
    • 如果你在 ajax 请求中使用 JSON.stringify({'key1': 'value1'})。控制器将其作为 json 对象接收,另一种情况发送:“key1=value1&key2=value2”,查询字符串。并且有必要使用 $request->get('key1')。我认为第一个更干净。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-09
    • 2013-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-08
    • 2013-06-08
    相关资源
    最近更新 更多