如何在树枝模板中访问JSON数据?

时间:2014-02-17 20:29:22

标签: php json symfony twig

我正在使用Symfony2并向api发出php curl请求。我希望确保以正确的形式返回结果:作为json 字符串(不是php对象或其他东西)。返回的json字符串由renderAPIResults()使用,它使用twig“渲染”JsonResponse。这可能吗?

我可以“渲染” renderAPIResults中的响应,还是我需要返回JsonResponse并使用twig模板渲染它,已经从apiAction()调用?

是否有任何内置的Symfony2功能,如果有人将模板命名为results.json.twigresults.html.twig,或者这个命名约定是否只是惯用的?

我已经能够通过在Response()方法中呈现renderAPIResults()将结果导入results.html.twig,但我只能console.log()来自.js的结果将结果作为JsonResponse()返回时的{1}}文件。在尝试某种方式“渲染”results.json.twig时,我无法在JsonResponse模板中以任何形式或形式解析这些结果。

 //DefaultController.php
 public function curlRestRequest($apiQueryString, $jsonDecode = FALSE, array $post_data = null, $service_url = null){

    if(!$service_url) {
        $service_url = 'http://website.com/rest';
    }

    $curl = curl_init($service_url.$apiQueryString);

    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);

    $curl_response = curl_exec($curl);

    if ($curl_response === false) {
        $info = curl_getinfo($curl);
        curl_close($curl);
        die('error occured during curl exec. Additioanl info: ' . var_export($info));
    }
    curl_close($curl);

    if($jsonDecode)
    {
        $curl_response = json_decode($curl_response);
    }

    return $curl_response;
}

public function renderAPIResults($data, $asObject = FALSE, $template)
{
    if(!$template) {
        throw new Exception('Must provide a template name before rendering!');
    }

    if($asObject != TRUE) {
        // we want to cast to array since specified as OBJECT = FALSE, removing all instances of objects
        $dataArray = json_decode(json_encode($data), true);
        return $this->render($template, array('data' => $dataArray));
    } else { // Is JSON Decoded, if it is an object
        //just return json data, parse it in javascript instead of with template

        $response = new JsonResponse();
        $response->setData(array(
            'data' => $data
        ));
        return $response;
        //return $this->renderView($template, array('data' => $data));
        //or
        //$content = $this->render($template, array('data' => $data));
        //return new JsonResponse($content);
    }
}

public function apiAction($type, $query){
  $apiQueryString = '/search/' . $type . '?query=' . $query;

  //make a curl request
  $requestedResults = ($this->curlRestRequest($apiQueryString, TRUE));

  //return option three: (dont use any response object, and just pass, just pass curl-results directly)
  //note, currently, when set as true, its not rendered in the template, the template is not used
  $view = $this->renderAPIResults($requestedResults, TRUE, 'ApiBundle:API:results.json.twig');
  return $view;
}

这是树枝模板:

//results.json.twig
{{ dump(data) }}

基本上,我问:

如何利用JsonResponse()方法中的renderAPIResults()在同一方法中呈现results.json.twig,返回此呈现的模板,以便模板本身可以循环json结果吗?

我可以使用JsonResponse()以这种方式呈现模板吗?或者在渲染时我只需要使用Response()方法吗?

如果我无法使用JsonResponse进行渲染,我可以使用其母语直接在树枝中解析结果吗?即{{ dump(results) }}或者我是否需要在脚本标签中包含javascript并首先处理这些结果?


编辑:我想我找到了问题的解决方案。

当你json_decode($ string,TRUE)时,如果它是一个深度嵌套的数组,那么嵌套的组件不会像我想象的那样最终成为一个完美的嵌套数组,只有顶层的数组才能。这是json_decode的自然副作用,还是坏json,或者我做错了什么?

我认为这篇文章有助于阐明这一点。 Accessing JSON array after json_decode/multidimensional array

所以看来我遇到的问题是JSON数据不完全干净。

即。

$requestedResults = ($this->curlRestRequest($apiQueryString, TRUE));
print_r($requestedResults);
//yields  Array
(
    [category] => 
    [executionTime] => 759
    [facets] => 
    [resultCount] => 8
    [searchCount] => 0
    [searchInfo] => 
    [searchResults] => Array
        (
            [0] => Array
                (
                    [description] => Gives instructions for 3 different in-class games.
                    [taxonomyDataSet] => {"course":[],"topic":[],"unit":[],"lesson":[],"subject":[],"curriculum":{"curriculumName":["Common Core State Standards - Math","Common Core State Standards - Math"],"curriculumCode":["CCSS.M.8.G.C.9","CCSS.M.7.G.B.6"],"curriculumDesc":["Solve real-world and mathematical problems involving area, volume and surface area of two- and three-dimensional objects composed of triangles, quadrilaterals, polygons, cubes, and right prisms.","Know the formulas for the volumes of cones, cylinders, and spheres and use them to solve real-world and mathematical problems."]}}
[thumbnail] => slides/thumbnail.jpg
                        [title] => Game Suggestions for Volume
                    )            
    )

其中“curriculumCode”用于例如不可访问,或taxonomyDataSet中的任何东西都无法访问,通过树枝,我不得不按摩数据有点清理它。

$requestedResults = ($this->curlRestRequest($apiQueryString, TRUE));

    foreach ($requestedResults['searchResults'] as $resource) {
        $title = $resource["title"];
        $description = $resource["description"];
        $thumbnailUrl = $resource["thumbnails"]['url'];
        $taxonomyDataSet = json_decode($resource['taxonomyDataSet'],TRUE);
        $standard = $taxonomyDataSet['curriculum']['curriculumCode'];
        if(! file_exists($thumbnailUrl))
        {
            $thumbnailUrl = NULL;
        }

        $results[] = array($title,$description,$thumbnailUrl, $standard);
    }
print_r($results);

//yields
Array
(
[0] => Array
    (
        [0] => Game Suggestions for Volume
        [1] => Gives instructions for 3 different in-class games.
        [2] => 
        [3] => Array
            (
                [0] => CCSS.M.8.G.C.9
                [1] => CCSS.M.7.G.B.6
            )

    ))

为什么我必须采取这个额外的步骤,是不是有更好的方法来正确迭代JSON字符串,所以这不会发生?

我更愿意将它保留为对象,然后在控制器return $requestedResults->searchResults中将其简单地返回 在没有所有数据量程的情况下,我可以安全地在TWIG中迭代它。

编辑,好好再深入研究一下这个,我相信公司的API数据是罪魁祸首,看起来结果的一个特定部分是双json_encoded,这就是为什么直到我按摩才能获得数据的原因它。是我,还是看起来这是发生了什么?

2 个答案:

答案 0 :(得分:0)

考虑使用FOSRestBundle,它会处理您的请求并返回正确的JSON响应"自动"。配置基本用法很简单,然后你必须遵循约定来实现简单有效的REST API。

您可以使用Guzzle作为API客户端来检索数据。您可以编写一些客户端类并提供实现某些逻辑的方法(每种资源的方法)。然后在这些方法中,您只需使用$response = $guzzleClient->get($url, $options),在$reponse->json()下,您就拥有了可以在自己的API响应中处理和提供的所有数据。

您应该将该API客户端注册为服务,并在自己的控制器中使用它来检索数据,然后处理它并从控制器的操作返回预期结果。您可以通过FOSRestBundle + JMSSerializerBundle处理它以进行JSON响应(您也可以返回XML,它是使用允许的格式和请求提供格式参数的资源的问题 - 例如获取/api/users.xml将返回XML文件,而/api/users.json将导致JSON)。

这是一个广泛的主题,几乎不可能描述你为了达到你想要的所有东西,但我相信它会帮助你获得正确的解决方案。

答案 1 :(得分:0)

我不确定我是否理解了这个问题,但我们走吧:

在我看来,您应该在将API结果发送到视图之前处理它,这意味着您应该将JSON字符串解析为PHP对象,创建它的数组,然后正常迭代twig。

因此,请集中精力开发一段代码,将您的JSON字符串转换为对象数组;并且不要将逻辑传递给视图。