我正在使用Symfony2并向api发出php curl请求。我希望确保以正确的形式返回结果:作为json 字符串(不是php对象或其他东西)。返回的json字符串由renderAPIResults()使用,它使用twig“渲染”JsonResponse
。这可能吗?
我可以“渲染” renderAPIResults
中的响应,还是我需要返回JsonResponse
并使用twig模板渲染它,已经从apiAction()调用?
是否有任何内置的Symfony2功能,如果有人将模板命名为results.json.twig
与results.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,这就是为什么直到我按摩才能获得数据的原因它。是我,还是看起来这是发生了什么?
答案 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字符串转换为对象数组;并且不要将逻辑传递给视图。