Vichuploaderbundle: How to get URL in Entity

Created on 29 Jun 2017  Â·  12Comments  Â·  Source: dustin10/VichUploaderBundle

I'm using this Bundle quite well but I'm looking for a way of getting the URL's of items in a FoS REST API result.

Currently, I'm saving just the filename to the entity, but I would prefer the full URL so that the API users can consume easier.

There are ways around this with manually adding the start of the URL and so on, but that's not a good solution.

I've used the asset helper in my twig templates with great success and I want to replicate this for my code.

My plan was to hook into the pre_inject event and use the helper class to get the URL and inject that into the property instead. However, I can't get any of the events to hook :/

Support

Most helpful comment

Thanks a lot @Koc!!!
I have modified the code a little bit removing all related to the $url array and CacheManager and it works perfect for me. The only thing is a deprecation in GenericSerializationVisitor that comes from the Serializer and will be a breaking change in a future update https://github.com/schmittjoh/serializer/pull/743

<?php

namespace App\EventSubscriber;

use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\ObjectEvent;
use JMS\Serializer\GenericSerializationVisitor;
use App\Entity\Image;
use Vich\UploaderBundle\Templating\Helper\UploaderHelper;

class ImageUrlsSubscriber implements EventSubscriberInterface
{
    private $uploaderHelper;

    public function __construct(UploaderHelper $uploaderHelper)
    {
        $this->uploaderHelper = $uploaderHelper;
    }

    public function onPostSerialize(ObjectEvent $event)
    {
        $object = $event->getObject();
        $visitor = $event->getVisitor();
        /* @var $visitor GenericSerializationVisitor */
        $path = $this->uploaderHelper->asset($object, 'imageFile');
        $visitor->setData('path', $path);
    }

    public static function getSubscribedEvents()
    {
        return array(
            array('event' => 'serializer.post_serialize', 'method' => 'onPostSerialize', 'class' => Image::class),
        );
    }
}

All 12 comments

I'm not sure to understand, are you trying to save the URL inside your entity?
And what do you mean with "I can't get any of the events to hook"

Sorry for my lack of clarity!

I'm using VichUploader to manage my image uploads, along with FlySystem to manage the file system abstraction.

I'm also using the FriendsOfSymfony REST bundle to create an API for our project.

The API endpoints for my entities need to provide the full URL of a file that has been uploaded, but instead all I can figure out from the VichUploader documentation is how to save the filename, or filesize.

Here's an example endpoint:

 {
    "title": "Deus Ex: Mankind Divided",
    "slug": "deus-ex-mankind-divided",
    "description": "Deus Ex: Mankind Divided directly follows the aftermath of the Aug Incident, a day when mechanically augmented citizens all over the world were stripped of control over their minds and bodies, resulting in the deaths of millions of innocents. \r\n\r\nThe year is now 2029, and the golden era of augmentations is over. Mechanically augmented humans have been deemed outcasts and segregated from the rest of society. Crime and acts of terror serve as a thin veil to cover up an overarching conspiracy aimed at controlling the future of mankind…",
    "box_art_url": "deus-ex-mankind-divided-box-art.jpg",
    "age_rating": {
        "name": "Mature",
        "board": "ERSB",
        "image_url": "ESRB_2013_Mature.png"
    }
}

This doc is covering how to generate URLs for assets

@garak yes, but he doesn't know where to call url generation :). Subscribe to pre_inject is totally wrong direction. http://jmsyst.com/libs/serializer/master/event_system is right.

Sorry fellas, I clicked close and comment by mistake. I hadn't quiet finished, but I think @Koc has figured it out for me. That does sound like the best and most ideal solution.

I had already planned on using that helper to generate the URL in code.

Also, I was listening on pre_inject and not seeing anything happening (tested by logging out some data). Alternatively, listening for pre_upload and post_upload did log out. Probably just my lack of understanding about the events here (though I have looked at the UploadHandler).

Anyway, cheers. I'll give that a shot.

Perfect, yep, hooking into the JMS Serializer was the way to go. Thanks guys.

@MatthewBooth feel free open PR with adding some howto section in docs https://github.com/dustin10/VichUploaderBundle/tree/master/Resources/doc which would help people solve issues like your.

@MatthewBooth, can you help do the same in my project? Thanks!

@picks44 I know it's a bit late, but anyway, I'll share the solution for anyone who's still looking for one:

Basically, you need to create an EventSubscriber somewhere in your bundle (in my case it is App\EventSubscriber\PhotoUrlSubscriber) with the following content (this assumes you are using Liip Imagine Bundle as well; if not, you can skip the $urls array and just add the $path):

<?php

namespace App\EventSubscriber;

use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\ObjectEvent;
use JMS\Serializer\GenericSerializationVisitor;
use Liip\ImagineBundle\Imagine\Cache\CacheManager;
use App\Entity\Photo;
use Vich\UploaderBundle\Templating\Helper\UploaderHelper;

class PhotoUrlsSubscriber implements EventSubscriberInterface
{
    private $uploaderHelper;
    private $cacheManager;

    public function __construct(UploaderHelper $uploaderHelper, CacheManager $cacheManager)
    {
        $this->uploaderHelper = $uploaderHelper;
        $this->cacheManager = $cacheManager;
    }

    public function onPostSerialize(ObjectEvent $event)
    {
        $object = $event->getObject();
        $visitor = $event->getVisitor();
        /* @var $visitor GenericSerializationVisitor */
        $path = $this->uploaderHelper->asset($object, 'file');
        $urls = array();
        foreach (array('carouselImage', 'carouselImage2x') as $pattern) {
            $urls[$pattern] = $this->cacheManager->getBrowserPath($path, sprintf('%s', $pattern));
        }
        $visitor->addData('image_urls', $urls);
    }
    public static function getSubscribedEvents()
    {
        return array(
            array('event' => 'serializer.post_serialize', 'method' => 'onPostSerialize', 'class' => Photo::class),
        );
    }
}

What this does is anytime the Photo Entity is serialized, the urls are added to the serialized object. This is pure genius, thanks to @Koc.

Thanks @finkbg !

Thanks a lot @Koc!!!
I have modified the code a little bit removing all related to the $url array and CacheManager and it works perfect for me. The only thing is a deprecation in GenericSerializationVisitor that comes from the Serializer and will be a breaking change in a future update https://github.com/schmittjoh/serializer/pull/743

<?php

namespace App\EventSubscriber;

use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\ObjectEvent;
use JMS\Serializer\GenericSerializationVisitor;
use App\Entity\Image;
use Vich\UploaderBundle\Templating\Helper\UploaderHelper;

class ImageUrlsSubscriber implements EventSubscriberInterface
{
    private $uploaderHelper;

    public function __construct(UploaderHelper $uploaderHelper)
    {
        $this->uploaderHelper = $uploaderHelper;
    }

    public function onPostSerialize(ObjectEvent $event)
    {
        $object = $event->getObject();
        $visitor = $event->getVisitor();
        /* @var $visitor GenericSerializationVisitor */
        $path = $this->uploaderHelper->asset($object, 'imageFile');
        $visitor->setData('path', $path);
    }

    public static function getSubscribedEvents()
    {
        return array(
            array('event' => 'serializer.post_serialize', 'method' => 'onPostSerialize', 'class' => Image::class),
        );
    }
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

manguecreative picture manguecreative  Â·  4Comments

Chrysweel picture Chrysweel  Â·  4Comments

fleskalebas picture fleskalebas  Â·  6Comments

petrjirasek picture petrjirasek  Â·  7Comments

jcg678 picture jcg678  Â·  6Comments