我一直在使用MongoDB尝试Symfony 2.2,FOSRest Bundle(使用JMS Serializer)和Doctrine ODM。
经过几个小时试图弄清楚如何正确设置FOSRest捆绑包后,我仍然遇到一些麻烦:我有一条非常简单的路线可以返回产品和价格清单。 每当我请求HTML格式时,我都会得到正确的响应,但如果我请求任何其他格式(JSON,XML),我会收到错误:
[{"message": "Resources are not supported in serialized data. Path: Monolog\\Handler\\StreamHandler -> Symfony\\Bridge\\Monolog\\Logger -> Doctrine\\Bundle\\MongoDBBundle\\Logger\\Logger -> Doctrine\\Bundle\\MongoDBBundle\\Logger\\AggregateLogger -> Doctrine\\ODM\\MongoDB\\Configuration -> Doctrine\\MongoDB\\Connection -> Doctrine\\ODM\\MongoDB\\LoggableCursor",
"class": "JMS\\Serializer\\Exception\\RuntimeException",...
您可以看到完整的错误消息here
我当前的设置非常简单:我创建了一条到控制器的单一路径,该路由器返回产品列表和价格(我跟着this example创建了产品文档)。
这是路线:
rest_product:
type: rest
resource: Onema\RestApiBundle\Controller\ProductController
这是控制器:
<?php
namespace Onema\RestApiBundle\Controller;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Routing\ClassResourceInterface;
use FOS\Rest\Util\Codes;
use JMS\Serializer\SerializationContext;
use Onema\RestApiBundle\Document\Product;
class ProductController extends FOSRestController implements ClassResourceInterface
{
public function getAction()
{
$dm = $this->get('doctrine_mongodb')->getManager();
$products = $dm->getRepository('RestApiBundle:Product')->findAll();
if(!$products)
{
throw $this->createNotFoundException('No product found.');
}
$data = array('documents' => $products);
$view = $this->view($data, 200);
$view->setTemplate("RestApiBundle:Product:get.html.twig");
return $this->handleView($view);
}
}
这是从控制器Resources / Product / get.html.twig调用的视图:
<ul>
{% for document in documents %}
<li>
{{ document.name }}<br />
{{ document.price }}
</li>
{% endfor %}
</ul>
任何想法为什么这对一种格式而不是其他格式正常工作?我还应该设置一些额外的东西吗?
更新 这是我一直在使用的配置值。 在app / config / config.yml的最后我有这个:
sensio_framework_extra:
view: { annotations: false }
router: { annotations: true }
fos_rest:
param_fetcher_listener: true
body_listener: true
format_listener: true
view:
formats:
json: true
failed_validation: HTTP_BAD_REQUEST
default_engine: twig
view_response_listener: 'force'
替代方法:
做了一些研究我遇到了另一个错误,这引出了我的问题并回答:
https://stackoverflow.com/a/14030646/155248
通过将每个结果添加到这样的数组中,我摆脱了Doctrine\ODM\MongoDB\LoggableCursor
:
$productsQ = $dm->getRepository('RestApiBundle:Product')->findAll();
foreach ($productsQ as $product) {
$products[] = $product;
}
return $products;
我开始以正确的格式获得结果。这是一种蹩脚的解决方案,仍然希望找到更好的答案来解决这个问题。
答案 0 :(得分:6)
如果要获取RestApiBundle:Product文档的集合,必须在从存储库调用find方法或从查询构建器调用getQuery方法后调用方法“toArray”
/**
* @Route("/products.{_format}", defaults={"_format" = "json"})
* @REST\View()
*/
public function getProductsAction($_format){
$products = $this->get('doctrine_mongodb')->getManager()
->getRepository('RestApiBundle:Product')
->findAll()->toArray();
return $products;
}
您也可以调用array_values($ products)来正确序列化排除策略
答案 1 :(得分:2)
错误最有可能出现在配置文件中或者可能缺少?添加你的配置,如果可以,我会更新我的答案。
现在我将向您介绍一个简单的实现。
首先让我们从配置开始:
注意:我将在某些设置中使用注释,请参阅SensioFrameworkExtraBundle。
#app/config/config.yml
sensio_framework_extra:
view:
annotations: false
fos_rest:
param_fetcher_listener: true
body_listener: true
format_listener: true
view:
view_response_listener: 'force'
首先我们设置sensio额外包。 default config使注释设置为true。我禁用了视图的注释(我不会在这里使用它们)。
对于fos_rest,我们正在设置Listeners,我们保持简单,所以我们将使用他们的文档中的示例。
我们将创建实体:
<?php
namespace Demo\DataBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints;
use JMS\Serializer\Annotation\ExclusionPolicy; //Ver 0.11+ the namespace has changed from JMS\SerializerBundle\* to JMS\Serializer\*
use JMS\Serializer\Annotation\Expose; //Ver 0.11+ the namespace has changed from JMS\SerializerBundle\* to JMS\Serializer\*
/**
* Demo\DataBundle\Entity\Attributes
*
* @ORM\Table()
* @ORM\Entity(repositoryClass="Demo\DataBundle\Entity\AttributesRepository")
*
* @ExclusionPolicy("all")
*/
class Attributes
{
/**
* @var integer $id
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*
* @Expose
*/
private $id;
/**
* @var string $attributeName
*
* @ORM\Column(name="attribute_name", type="string", length=255)
*
* @Expose
*/
private $attributeName;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set attributeName
*
* @param string $attributeName
* @return Attributes
*/
public function setAttributeName($attributeName)
{
$this->attributeName = $attributeName;
return $this;
}
/**
* Get attributeName
*
* @return string
*/
public function getAttributeName()
{
return $this->attributeName;
}
}
您会注意到几个注释设置。首先我们设置@ExclusionPolicy(“all”)然后我们手动设置我们想要@Expose到API的对象。您可以详细了解此here和JMS Serializer annotations
列表现在让我们转到一个简单的控制器:
<?php
namespace Demo\DataBundle\Controller;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Controller\Annotations as Rest; //Lets use annotations for our FOSRest config
use FOS\RestBundle\Routing\ClassResourceInterface;
use FOS\Rest\Util\Codes;
use Symfony\Component\HttpFoundation\Request;
use Demo\DataBundle\Entity\Attributes;
class AttributesController extends FOSRestController implements ClassResourceInterface
{
/**
* Collection get action
* @var Request $request
* @return array
*
* @Rest\View()
*/
public function cgetAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('DemoDataBundle:Attributes')->findAll();
return array(
'entities' => $entities,
);
}
}
这是一个简单的控制器,可以返回所有内容。
希望这有帮助。我认为您的错误来自与Serializer相关的错误设置。确保您公开了一些数据。