7

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

service: vich_uploader.namer_property
options: { property: 'slug'}

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

/**
 * @Gedmo\Slug(fields={"title"}, updatable=false)
 * @ORM\Column(type="string", length=100, nullable=false)
 */
protected $slug;

但是在尝试保存实体时,我收到以下错误 500:

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

如果我将属性设置为“标题”,它会起作用。我是否忘记了配置参数或其他东西以使其与 Gedmo slug 一起使用?

4

4 回答 4

3

我现在遇到了同样的问题,作为一种解决方法,我稍微改变了实体类中的 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;
    }
}

那成功了。

不幸的是,有几个缺点:

  1. 如果您想更新注释中的 sluggable 行为以包含其他属性,则还必须更新 getter。
  2. 这种方法缺少对数据库的检查:如果数据库中已经有一条同名的记录在urlizergetter中将无法为文件名添加增量,以前保存的文件可能会被覆盖!作为一种解决方法,您可以添加unique=true到 sluggable 属性。
于 2018-07-20T03:44:05.167 回答
2

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 并重新保存实体而不上传新文件,则文件名不会更新。

于 2020-02-05T12:47:36.187 回答
1

我在上传需要文件名作为 slug 的文档时遇到了同样的问题。

我使用 Gedmo 注释来生成 slug,但这只会在刷新时触发,而 vichUploader 命名器会在持久化时触发。

我最简单的方法是不使用 Gedmo\Sluggable 注释,而是在我的 Document 对象上创建一个 prePersist 侦听器并使用 Cocur\Slugify 库。

所以这里是代码。

我的文档实体:

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);
        }
    }
}

到目前为止,我还没有遇到任何问题。

让我知道这是否适合您

于 2019-05-22T09:54:56.183 回答
0

默认情况下,学说扩展包不附加任何侦听器: http ://symfony.com/doc/current/bundles/StofDoctrineExtensionsBundle/index.html#activate-the-extensions-you-want

您应该对其进行配置以使其正常工作:

stof_doctrine_extensions:
    orm:
        default:
            sluggable: true
于 2016-03-02T15:55:23.647 回答