将JSON对象发布到Symfony 2


71

我正在使用Symfony 2开发一个项目,我已经构建了一个捆绑包来处理我的所有数据库服务,该服务将来回传递JSON数据。

我的问题/问题:

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

  • 我希望能够使用一个服务包来处理来自AJAX调用或常规Symfony形式的数据。目前,我正在使用提交的Symfony表单,然后使用JSON_ENCODE获取数据,但是我无法弄清楚如何将数据发布到期望请求数据的服务控制器中。

总结一下:

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

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

如果我要解决所有这些错误,请随时告诉我!

Answers:


138

如果要在控制器中检索已作为请求主体中的标准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数据的数组。删除调用中的true参数值json_decode()以获取stdClass对象。


感谢您的回复。我实际上是通过这种方式在周末工作的:$ JSON = file_get_contents(“ php:// input”); 这样有什么问题吗?
greg 2012年

19
php://input是一次性的。阅读内容后,除非再传递这些数据,否则无法再次阅读。使用Symfony2 Request对象可确保您可以在需要时再次获取数据,而无需传递$JSON变量。
richsage 2012年

3
一个小错字和答案。该函数需要request参数:公共函数yourAction(Request $ request)
greg

2
@whistlergreg没有问题!:-)通过参数传递请求对象是可选的;您应该能够按照上面的代码将其遗漏并从容器中获取,或者传递给它。有关不同的变体,请参见此处此处
richsage 2012年

1
这个有一个问题:您不能将这样的请求绑定到表单。有办法吗?
Vitaliy Lebedev

10

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

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

1
验证器类在symfony上默认存在吗?
Mohamed Radhi Guennichi

数组没有方法,兄弟。
ЯрославРахматуллин

ArrayCollection是一个类。
Farid Movsumov

1

页面上的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对象发送给另一个服务?
greg 2012年

我在编辑中回答了您的评论。我不太确定如何在不使用jQuery的情况下进行Ajax处理,所以请留给您。要将某人发送到另一个控制器,您可以在那里将他们重定向。这是覆盖在symfony.com/doc/2.0/book/controller.html重定向转发。祝好运!
ЯрославРахматуллин

再次感谢您,我应该更清楚一点,我可以毫无问题地提交对象,我无法弄清楚如何在没有名称的情况下在控制器中检索它
greg

$ request-> request-> get('action',null)等于$ request-> request-> get('action')
Bill'o 2014年

如果您在Ajax请求中使用JSON.stringify({'key1':'value1'})。控制器将其作为json对象接收,另一种情况发送:“ key1 = value1&key2 = value2”,查询字符串。并且将需要使用$ request-> get('key1')。我认为第一个是清洁工。
Felix Aballi 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.