Sylius/Symfony:使用自定义实体上传图片

Sylius/Symfony: Image Upload with custom entity

我正在尝试将 Sylius 的 ImagesUploadListener 用于自定义实体。 在 documentation 中,它说我应该听 "sylius.shipping_method.pre_create" 这样的事件。对于我的自定义实体,没有我可以挂接的事件。

所以我尝试挂钩 product.pre_create 事件并将我的实体作为参数,但似乎图片上传仅在产品实体上触发,我的实体配置被忽略。尽管 ImagesUploadListener 被触发了两次,一次来自核心,一次来自我的配置。

我得到的错误是 "Column 'path' cannot be null",这基本上意味着 ImagesUploadListener 在保存实体之前没有执行图像上传。

    app.listener.images_upload:
        class: Sylius\Bundle\CoreBundle\EventListener\ImagesUploadListener
        parent: sylius.listener.images_upload
        autowire: true
        autoconfigure: false
        public: false
        tags:
            - { name: kernel.event_listener, event: sylius.product.pre_create, entity: MyBundle\Entity\MyEntity, method: uploadImages }

如果您正确创建实体(Sylius 方式),应该有一个事件可以挂钩。您需要将实体定义为资源:

# config/packages/sylius_resource.yaml
sylius_resource:
    resources:
        app.name_of_etity:
            driver: doctrine/orm
            classes:
                model: App\Entity\NameOfEntity

如果您这样定义资源,事件将是:

event: app.system_manual.pre_create
event: app.app.name_of_entity.pre_update

遵循本指南: https://docs.sylius.com/en/1.6/cookbook/entities/custom-model.html

更新

因为您是通过现有产品表单管理您的自定义实体,所以上述方法将不起作用。要使其工作,您可以创建自己的事件侦听器。

final class ProductSeoTranslationImagesUploadListener
{
    /** @var ImageUploaderInterface */
    private $uploader;

    public function __construct(ImageUploaderInterface $uploader)
    {
        $this->uploader = $uploader;
    }

    public function uploadImages(GenericEvent $event): void
    {
        $subject = $event->getSubject();
        // Add a ProductSeoInterface so you can use this check: 
        Assert::isInstanceOf($subject, ProductSeoInterface::class);
        foreach ($subject->getSeo()->getTranslations() as $translation) {
            Assert::isInstanceOf($translation, ImagesAwareInterface::class);
            $this->uploadSubjectImages($translation);
        }
    }

    private function uploadSubjectImages(ImagesAwareInterface $subject): void
    {
        $images = $subject->getImages();
        foreach ($images as $image) {
            if ($image->hasFile()) {
                $this->uploader->upload($image);
            }

            // Upload failed? Let's remove that image.
            if (null === $image->getPath()) {
                $images->removeElement($image);
            }
        }
    }
}

提示:创建一个 (Product)SeoInterface 以便您可以执行类型检查。

别忘了注册事件监听器:

App\EventListener\ProductSeoTranslationImagesUploadListener:
        tags:
            - {
                  name: kernel.event_listener,
                  event: sylius.product.pre_create,
                  method: uploadImages,
              }
            - {
                  name: kernel.event_listener,
                  event: sylius.product.pre_update,
                  method: uploadImages,
              }