2

我正在配置VichUploaderBundle中包含的目录命名器以上传多个文件。

我有两个实体SoundtrackSong. s的集合Song在我的控制器中处理,如下所示:

//...
if ($form->isValid()) {
   $soundtrack->setSlug("sw-ep-vii");
   $soundtrack->setName("Star Wars Episode VII");
   foreach ($soundtrack->getSongs() as $song) {
      $em->persist($song);
   }
   $em->persist($soundtrack);
   $em->flush();
}

持久$soundtrack VichUploaderBundle化上传Song文件并将它们移动到定义的目录config.yml或一个名为 的服务中定义的动态路由DirectoryNamer,这是我感兴趣的。

在我SoundtrackDirectoryNamer的 中,持久Song实体自动传递给该directoryName()方法,因此我只想将关联Soundtrack.id的作为目录名称返回,例如:

class SoundtrackDirectoryNamer implements DirectoryNamerInterface
{
    public function directoryName($song, PropertyMapping $mapping)
    {   
        return $song->getSoundtrack()->getId();                                                                                    
    }
}

现在问题Soundtrack仍然没有持久化到数据库,所以它还没有自动递增id

如果我更改$song->getSoundtrack()->getId()$song->getSoundtrack()->getSlug(),它会正确创建目录sw-ep-vii并且一切正常 - 正如我之前在控制器中使用$soundtrack->setSlug("sw-ep-vii").

有什么解决方法吗?

4

2 回答 2

4

我是该捆绑包的当前维护者。

这是一个已知问题(确切地说,它是一个无法解决的问题)。

目录和文件名是在实体实际保存之前计算的,因此对于新对象,标识符不可用。按照设计,没有什么可以避免这种情况……除非您不使用自动递增的标识符而是使用生成的标识符(例如 UUID 或 slug)。

于 2015-11-30T16:38:21.277 回答
0

实际上有一个解决方案,即使它可能不是在所有情况下都完全可靠。这是一个与 MySQL 兼容的示例方法,您可以将其放入您的命名器类中以获取新实体的预期 id(前提是注入的实体管理器):

protected function getNextAutoIncrementedId($object) {
  $meta = $this->em->getClassMetadata(get_class($object));
  if(!$meta) return null;

  $conn = $this->em->getConnection();
  $table = $meta->getTableName();
  $sql = "SHOW TABLE STATUS WHERE `Name` = '$table'";
  $result = $conn->query($sql)->fetch(\PDO::FETCH_ASSOC);
  if(empty($result['Auto_increment'])) return null;

  return $result['Auto_increment'];
}
于 2016-11-02T10:37:49.823 回答