VichUploaderBundle:如何获取 DirectoryNamer 中的相关实体 ID?
VichUploaderBundle: How to get related entity ID in DirectoryNamer?
我正在配置一个 directory namer included in VichUploaderBundle 来上传多个文件。
我有两个实体 Soundtrack
和 Song
。 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
中定义的目录或在名为 [= 的服务中定义的动态路由19=],这是我感兴趣的。
在我的 SoundtrackDirectoryNamer
中,持续的 Song
实体自动传递给 directoryName()
方法,所以我只想 return 关联的 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")
在控制器中设置了 slug .
有什么解决方法吗?
我是该包的当前维护者。
这是一个已知问题(确切地说,不会修复)。
在实际保存实体之前计算目录和文件名,因此对于新对象,标识符不可用。按照设计,没有任何办法可以避免这种情况……除非您不使用自动递增的标识符而是使用生成的标识符(例如 UUID 或 slugs)。
实际上有一个解决方案,即使它可能不是在所有情况下都完全可靠。这是一个与 MySQL 兼容的示例方法,您可以将其放入您的命名器 class 中以获取新实体的预期 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'];
}
我正在配置一个 directory namer included in VichUploaderBundle 来上传多个文件。
我有两个实体 Soundtrack
和 Song
。 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
中定义的目录或在名为 [= 的服务中定义的动态路由19=],这是我感兴趣的。
在我的 SoundtrackDirectoryNamer
中,持续的 Song
实体自动传递给 directoryName()
方法,所以我只想 return 关联的 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")
在控制器中设置了 slug .
有什么解决方法吗?
我是该包的当前维护者。
这是一个已知问题(确切地说,不会修复)。
在实际保存实体之前计算目录和文件名,因此对于新对象,标识符不可用。按照设计,没有任何办法可以避免这种情况……除非您不使用自动递增的标识符而是使用生成的标识符(例如 UUID 或 slugs)。
实际上有一个解决方案,即使它可能不是在所有情况下都完全可靠。这是一个与 MySQL 兼容的示例方法,您可以将其放入您的命名器 class 中以获取新实体的预期 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'];
}