Reputation: 143
I'm working on a mobile app that has to show some images of houses from a server. I have installed Symfony2, FOSRestBundle and Sonata Media Bundle for the backend.
In order to get the houses images URLs, I have configured FOSRestBundle for an entity named Property which has a gallery field. This is the REST controller
class PropertiesController extends FOSRestController
{
public function getPropertiesAction()
{
$response = $this->getDoctrine()->getRepository('ComissionBundle:Property')->findAll();
if ($response == null){
return "No properties";
}
else{
return $response;
}
}
}
But i get this:
[
{
"id":2,
"name":"test",
"city":"test",
"address":"test",
"sector":"test",
"area":0,
"rooms":112343,
"price":0,
"gallery":{
"context":"default",
"name":"test",
"enabled":false,
"updated_at":"2016-08-26T17:18:51+0200",
"created_at":"2016-08-26T17:18:51+0200",
"default_format":"default_small",
"id":1
}
}
]
As you can see, there are no media objects.
Then, I tried with a customized repository method:
class PropertyRepository extends EntityRepository
{
public function findMainInfoElements($elements)
{
$em = $this->getEntityManager();
$queryText = "SELECT u, g, h FROM ComissionBundle:Property u JOIN u.gallery g JOIN g.galleryHasMedias h";
$query = $em->createQuery($queryText);
return $query->setMaxResults($elements)->getResult();
}
}
but the result is the same.
How can i get the URLs from the gallery in order to show them in the mobile app? (Especially the thumb images that Sonata Media Bundle generates, which are better for the app performance)
Upvotes: 1
Views: 1480
Reputation: 1415
Here's is how I did it in a legacy project that I'm working on, adapting the code suggested by @seltzlab:
<?php
namespace Casinos\ApiBundle\Serializer\Handler;
use Application\Sonata\MediaBundle\Entity\Gallery;
use JMS\Serializer\JsonSerializationVisitor;
use JMS\Serializer\Context;
use Sonata\MediaBundle\Provider\ImageProvider;
class MediaGalleryHandler
{
/**
* @var ImageProvider
*/
private $imageProvider;
public function __construct(ImageProvider $imageProvider)
{
$this->imageProvider = $imageProvider;
}
public function serializeMedia(JsonSerializationVisitor $visitor, Gallery $media, array $type, Context $context)
{
$serializedMedias = [];
foreach ($media->getGalleryHasMedias() as $galleryHasMedia) {
$media = $galleryHasMedia->getMedia();
$serializedMedias[] = $this->imageProvider->generatePublicUrl($media, "reference");
}
if ($visitor->getRoot() === null) {
$visitor->setRoot($serializedMedias);
}
return $serializedMedias;
}
}
Upvotes: 0
Reputation: 340
I guess you should join the galleryHasMedia entity with the Media entity too in the PropertyRepository query, but it will not be enough. You should create a custom serialization handler for the Media entity too.
Declare the serialization handler
myapp.serialization.media_handler:
class: Path\ToYourApp\Serializer\MediaSerializationHandler
tags:
- { name: jms_serializer.handler, type: Path\ToYourMedia\Entity\Media, direction: serialization, format: json, method: serializeMedia }
arguments: [ @sonata.media.provider.image, @sonata.media.provider.file ]
Create the serialization handler
<?php
namespace Camelot\Social\ApiBundle\Serializer;
use Path\ToYourMedia\Entity\Media;
use JMS\Serializer\JsonSerializationVisitor;
use JMS\Serializer\Context;
use Sonata\MediaBundle\Provider\ImageProvider;
use Sonata\MediaBundle\Provider\FileProvider;
class MediaSerializationHandler
{
/**
* @var ImageProvider
*/
private $imageProvider;
/**
* @var FileProvider
*/
private $fileProvider;
public function __construct(ImageProvider $imageProvider, FileProvider $fileProvider)
{
$this->imageProvider = $imageProvider;
$this->fileProvider = $fileProvider;
}
public function serializeMedia(JsonSerializationVisitor $visitor, Media $media, array $type, Context $context)
{
switch ($media->getProviderName()) {
case 'sonata.media.provider.file':
$serialization = $this->serializeFile($media);
break;
case 'sonata.media.provider.image':
$serialization = $this->serializeImage($media);
break;
default:
throw new \RuntimeException("Serialization media provider not recognized");
}
if ($visitor->getRoot() === null) {
$visitor->setRoot($serialization);
}
return $serialization;
}
private function serializeImage(Media $media)
{
// here you can provide one ore more URLs based on your SonataMedia configuration
// you can also add some more properties coming from the media entity based on your needs (e.g. authorName, description, copyright etc)
return [
"url" => [
"orig" => $this->imageProvider->generatePublicUrl($media, "reference"),
"small" => $this->imageProvider->generatePublicUrl($media, "default_small"),
"big" => $this->imageProvider->generatePublicUrl($media, "default_big"),
]
];
}
private function serializeFile(Media $media)
{
return [
"name" => $media->getName(),
"size" => $media->getSize(),
"url" => $this->fileProvider->generatePublicUrl($media, 'reference')
];
}
}
Upvotes: 1