Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exporting file/image doesn't work with inherited entity #1

Closed
kwn opened this issue Jan 14, 2015 · 6 comments
Closed

Exporting file/image doesn't work with inherited entity #1

kwn opened this issue Jan 14, 2015 · 6 comments

Comments

@kwn
Copy link

kwn commented Jan 14, 2015

Hello,

I'm trying to export an user's avatar. My user entity extends FOSUserBundle:User. My configuration:

# app/config/config.yml
hshn_serializer_extra:
    vich_uploader:
        classes:
            "App\GeneralBundle\Entity\ProductImage": # this works without any problem
                files:
                    - { property: product, export_to: image }
                    - { property: product, export_to: thumbnail, filter: thumb_square }
            "App\GeneralBundle\Entity\User": # this doesn't work
                files:
                    - { property: avatar, export_to: avatar, filter: thumb_square }

JMS\Expose() annotation works (after using additional directory with metadata). What is more, if I set Expose() to $avatar field in User entity it exposes (as a empty object).

@hshn
Copy link
Owner

hshn commented Jan 15, 2015

@kwn

Hi, Thank you for your reporting.

IMO this issue is caused if the entity is a doctrine proxy.

So I've added some patch.
Could you try again using new release v0.4.1?

@kwn
Copy link
Author

kwn commented Jan 15, 2015

@hshn
Hi Shota,

Thanks for your reply. I tried with 0.4.1 version and unfortunately I still can't see exported VichUploader based field. I remember to clear a cache.

Once again I'm putting a complete config and complete json output, maybe I'm doing something wrong. Anyway thanks for your work! It's a great and very helpful bundle.

# app/config/config.yml
hshn_serializer_extra:
    vich_uploader:
        classes:
            "App\GeneralBundle\Entity\ProductImage": # works fine
                files:
                    - { property: product, export_to: image }
                    - { property: product, export_to: thumbnail, filter: thumb_square }
            "App\GeneralBundle\Entity\User": # doesn't work with or without "export_to" nor "thumbnail"
                files:
                    - { property: avatar }
            "App\GeneralBundle\Entity\Badge": # works fine
                files:
                    - { property: badge, export_to: image }
                    - { property: badge, export_to: thumbnail, filter: thumb_square }

jms_serializer:
    metadata:
        directories:
            FOSUserBundle:
                namespace_prefix: "FOS\\UserBundle"
                path: "%kernel.root_dir%/Resources/FOSUserBundle/serializer"
# app/Resources/FOSUserBundle/serializer/Model.User.yml
FOS\UserBundle\Model\User:
    exclusion_policy: ALL
    properties:
        id:
            expose: true
        username:
            expose: true
        slug:
            expose: true
# I tried to expose here an avatar field as well, but it didn't help
// src/GeneralBundle/Entity/User.php

use FOS\UserBundle\Model\User as BaseUser;
// [...]

/**
 * User
 *
 * @ORM\Table(name="user")
 * @ORM\Entity(repositoryClass="App\GeneralBundle\Repository\UserRepository")
 * @Vich\Uploadable()
 * @JMS\ExclusionPolicy("all")
 */
class User extends BaseUser
{
    // [...]

    /**
     * @var string
     *
     * @ORM\Column(name="location", type="string", length=255, nullable=true)
     * @Assert\Length(max="255")
     * @JMS\Expose()
     */
    protected $location;

    /**
     * @var string
     *
     * @ORM\Column(name="bio", type="text", nullable=true)
     * @Assert\Length(max="10000")
     * @JMS\Expose()
     */
    protected $bio;

    /**
     * @var string
     *
     * @ORM\Column(name="avatar_filename", type="string", length=255, nullable=true)
     * @Assert\Length(max="255")
     */
    protected $avatarFilename;

    /**
     * @var File
     *
     * @Assert\File(
     *     maxSize="2M",
     *     mimeTypes={"image/png", "image/jpeg", "image/pjpeg"}
     * )
     * @Assert\NotBlank(groups={"Avatar"})
     * @Vich\UploadableField(mapping="avatar", fileNameProperty="avatarFilename")
     */
    protected $avatar;

    // [...]
}

Serialized user without @JMS\Expose() annotation in $avatar field.

{
  id: 5
  username: "Alotro"
  slug: "alotro"
  location: "Poznań"
  bio: "<p>...</p> "
  blog: null
}

User with @JMS\Expose() annotation in $avatar field.

{
  id: 5
  username: "Alotro"
  slug: "alotro"
  location: "Poznań"
  bio: "<p>...</p> "
  blog: null
  avatar: {}
}

@kwn
Copy link
Author

kwn commented Jan 24, 2015

Hi @hshn

Today I find out, why I don't get an avatar fields in serialized User entity. The reason is very simple, I just didn't upload any picture as an avatar into an entity! Entities that have uploaded avatar file works fine.

It's because here:

// hshn/serializer-extra-bundle/src/VichUploader/EventSubscriber.php

    public function onPostSerialize(ObjectEvent $event)
        // [...]
        foreach ($files as $file) {
            try {
                $visitor->addData($file->getExportTo(), $this->uriResolver->resolve($object, $file, $configuration->getClass()));
            } catch (UriResolverException $e) {
            }
        }
    }

there is an exception caught and nothing happens with that. No new key is added to serialized object.

Actually developer doesn't know what happened. This can cause an unexpected behavior in your frontend, if you try to access a key that doesn't exist.

So what I suggest, is to add the defined property to serialized entity with null value.

        foreach ($files as $file) {
            try {
                $visitor->addData($file->getExportTo(), $this->uriResolver->resolve($object, $file, $configuration->getClass()));
            } catch (UriResolverException $e) {
                $visitor->addData($file->getExportTo(), null);
            }
        }

What do you think about this solution? I can prepare a PR if you want, but it's just a one line and test to fix.

@hshn
Copy link
Owner

hshn commented Jan 26, 2015

Hi @kwn

Thank you for your descriptions. I'd been trying to reproduce this issue but that was unexpected.

Actually developer doesn't know what happened. This can cause an unexpected behavior in your frontend, if you try to access a key that doesn't exist.

I agreed. However I think the default serialization behavior of JMSSerializerBundle does not expose null value including its attribute. It depends on SerializationContext. (Also max_depth should be effected by the context too.)

So I think we should improve exposing behavior to be same as jms/serializer.

Thank you for your suggestion!
I'll implement it in the near feature.

@hshn hshn closed this as completed Jan 26, 2015
@kwn
Copy link
Author

kwn commented Jan 26, 2015

Hello @hshn

Thank you for answering me.

Actually you are right, JSMSerializer doesn't expose null but you can set an option in FOSRestBundle configuration to do that:

fos_rest:
    [...]
    serializer:
        serialize_null: true

I'm pretty sure, that your bundle will be related to FOSRestBundle in most cases, so you can consider introducing a similar option as well.

Anyway, thank you for this bundle again. You saved a lot of my time :)

@hshn
Copy link
Owner

hshn commented Jan 26, 2015

It's my pleasure :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants