I have been trying out Symfony 2.2, the FOSRest Bundle (using JMS Serializer), and Doctrine ODM using MongoDB.
After many hours of trying to figure out how to correctly setup the FOSRest Bundle I'm still having some trouble: I have a very simple route that returns a list of products and prices. Whenever I request for the HTML format I get the correct response, but if I request any other format (JSON, XML) I get an error:
[{"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",...
you can see the full error message here
My current setup is very simple: I have created a single route to a controller that returns a list of products and the price (I followed this example to create the product document).
This is the route:
rest_product:
type: rest
resource: Onema\RestApiBundle\Controller\ProductController
This is the controller:
<?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);
}
}
This is the view called from the controller Resources/Product/get.html.twig:
<ul>
{% for document in documents %}
<li>
{{ document.name }}<br />
{{ document.price }}
</li>
{% endfor %}
</ul>
Any ideas why this would work correctly for one format but not the others? Anything additional I'm supposed to setup?
UPDATE: This is the config values I have been using. At the end of app/config/config.yml I had this:
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'
WORKAROUND:
Doing a bit more research I ran into another error which lead me to this questions and answer:
https://stackoverflow.com/a/14030646/155248
Once I got rid of the Doctrine\ODM\MongoDB\LoggableCursor
by adding every result to an array like this:
$productsQ = $dm->getRepository('RestApiBundle:Product')->findAll();
foreach ($productsQ as $product) {
$products[] = $product;
}
return $products;
I started getting the results in the correct format. This is kind of a lame solution and still hope to find a better answer to this issue.
If you want to get a colection of RestApiBundle:Product documents, you MUST call the method "toArray" after calling find method from repository or getQuery method from query builder
/**
* @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;
}
also you can call array_values($products) for correct serialization of exclude strategy