Php Symfony VichUploaderBundle:无法生成文件名

Php Symfony VichUploaderBundle:无法生成文件名,php,symfony,vichuploaderbundle,Php,Symfony,Vichuploaderbundle,我正在使用VichUploader上载symfony项目中的文件。在我使用的配置中(从文档中复制): 在我的实体中,我使用Gedmo/slaggable自动生成slug: /** * @Gedmo\Slug(fields={"title"}, updatable=false) * @ORM\Column(type="string", length=100, nullable=false) */ protected $slug; 但在尝试保存实体时,我遇到以下错误500: 无法生成文件名:

我正在使用VichUploader上载symfony项目中的文件。在我使用的配置中(从文档中复制):

在我的实体中,我使用Gedmo/slaggable自动生成slug:

/**
 * @Gedmo\Slug(fields={"title"}, updatable=false)
 * @ORM\Column(type="string", length=100, nullable=false)
 */
protected $slug;
但在尝试保存实体时,我遇到以下错误500:

无法生成文件名:属性slug为空


如果我将属性设置为“title”,它将工作。我是否忘记了一个配置参数或其他使其与Gedmo slug一起工作的东西?

默认情况下,条令扩展包不附加任何侦听器:

您应该将其配置为使Slagable工作:

stof_doctrine_extensions:
    orm:
        default:
            sluggable: true

目前我也遇到了同样的问题,作为一种解决方法,我稍微更改了entity类中的slug getter:

use Gedmo\Sluggable\Util\Urlizer;

class Event
{
    // ...

    /**
     * @var string
     *
     * @Gedmo\Slug(fields={"name"})
     * @ORM\Column(name="slug", type="string", length=128, unique=true)
     */
    private $slug;

    // ...

    public function getSlug()
    {
        if (!$this->slug) {
            return Urlizer::urlize($this->getName());
        }

        return $this->slug;
    }
}
这就成功了

不幸的是,有几个缺点:

  • 如果您想要更新注释中的slaggable行为以包含其他属性,那么还必须更新getter
  • 此方法缺少对数据库的检查:如果数据库中已有一条记录具有相同的名称
    urlizer
    ,则getter将无法向文件名添加增量,以前保存的文件可能会被覆盖!作为一种解决方法,您可以将
    unique=true
    添加到Slaggable属性

  • 我在上传一个文件时遇到了同样的问题,我需要文件名作为slug

    我使用Gedmo注释来生成slug,但是这只在flush时触发,而vichUploader名称在persist时触发

    对于我来说,最简单的方法是不使用Gedmo\slaggable注释,而是在我的文档对象上创建一个prePersist侦听器,并使用Cocur\slagify库

    这是代码

    我的文档实体:

    namespace App\Entity;
    
    use Doctrine\ORM\Mapping as ORM;
    use Gedmo\Timestampable\Traits\TimestampableEntity;
    use Symfony\Component\HttpFoundation\File\File;
    use Vich\UploaderBundle\Mapping\Annotation as Vich;
    
    /**
     * @ORM\Entity(repositoryClass="App\Repository\DocumentRepository")
     * @Vich\Uploadable
     * @ORM\EntityListeners({"App\Listeners\DocumentListener"})
     */
    class Document
    {
        use TimestampableEntity;
    
        /**
         * @ORM\Id()
         * @ORM\GeneratedValue()
         * @ORM\Column(type="integer")
         */
        private $id;
    
    
        /**
         * @ORM\Column(type="string", length=100, nullable=false)
         */
        private $fileName;
    
        /**
         * @Vich\UploadableField(mapping="document", fileNameProperty="fileName")
         * @var File
         */
        private $documentFile;
    
        /**
         * @ORM\Column(type="string", length=100, unique=true)
         */
        private $slug;
    
        /**
         */
        public function getDocumentFile(): ?File
        {
            return $this->documentFile;
        }
    
        /**
         * @param File $documentFile
         * @return Document
         * @throws \Exception
         */
        public function setDocumentFile(File $documentFile = null): Document
        {
            $this->documentFile = $documentFile;
            if($documentFile){
                $this->updatedAt = new \DateTimeImmutable();
            }
    
            return $this;
        }
    
        public function getId(): ?int
        {
            return $this->id;
        }
    
        public function getSlug(): ?string
        {
            return $this->slug;
        }
    
        public function setSlug(string $slug): self
        {
            $this->slug = $slug;
    
            return $this;
        }
    
        /**
         * @return mixed
         */
        public function getFileName()
        {
            return $this->fileName;
        }
    
        /**
         * @param mixed $fileName
         */
        public function setFileName($fileName): void
        {
            $this->fileName = $fileName;
        }
    }
    
    听众:

    namespace App\Listeners;
    
    use App\Entity\Document;
    use Doctrine\ORM\Event\LifecycleEventArgs;
    use Cocur\Slugify\Slugify;
    
    class DocumentListener
    {
        public function prePersist(Document $document, LifecycleEventArgs $args)
        {
            $slugify = new Slugify();
            if(!empty($document->getDocumentFile())){
                $originalName = pathinfo($document->getDocumentFile()->getClientOriginalName(), PATHINFO_FILENAME);
                $slug = $slugify->slugify($originalName);
                $document->setSlug($slug);
            }
        }
    }
    
    到目前为止,我还没有遇到任何问题


    让我知道这是否适用于您

    VichUploader侦听prePersist和preUpdate事件,而Sluggable侦听onFlush事件。因为prePersist和preUpdate是在onFlush之前调用的,所以纯粹使用配置是不可能做到这一点的

    但是,如果文件字段可为空,则可以通过更改控制器代码来解决此问题。收到提交的表单和文件后,删除该文件,保存实体,然后重新添加该文件并再次保存实体。在第二次保存时,slug已经被设置,因此VichUploader将能够很好地保存文件

    if ($form->isSubmitted() && $form->isValid()) {
        if ($file = $entity->getFile()) {
            $entity->setFile(null);
        }
        
        $em = $this->getDoctrine()->getManager();
        $em->persist($entity);
        $em->flush();
        
        if ($file) {
            $entity->setFile($file);
            $em->persist($entity);
            $em->flush();
        }
        
        // ...
    }
    

    这仅在添加新文件时有效。如果随后更改slug并重新保存实体而不上载新文件,则文件名不会更新。

    我猜原因是两个捆绑包都使用
    flush
    事件进行操作,并且以错误的顺序执行……但是有机会配置吗?@Nicki您找到了该怎么做吗?我刚刚遇到了同样的问题-我更改了vich_uploader.namer_uniqid的名称作为一个快速修复,但这不是我想要的。slug是生成的,但它似乎是在VichUploader尝试访问它之后生成的。@Nicki和您的
    config.yml
    中有上面的配置?不是确切的配置,因为我在没有StofBundle的情况下安装了Gedmo。但是监听器已经配置好,并生成了slug。
    if ($form->isSubmitted() && $form->isValid()) {
        if ($file = $entity->getFile()) {
            $entity->setFile(null);
        }
        
        $em = $this->getDoctrine()->getManager();
        $em->persist($entity);
        $em->flush();
        
        if ($file) {
            $entity->setFile($file);
            $em->persist($entity);
            $em->flush();
        }
        
        // ...
    }