在 Symfony 中为实体 属性 生成预签名 URL 的最佳方法
Best approach to generate presigned URL for entity property in Symfony
我有一个 User 对象,它有一个 profilePicturePresignedUrl 属性。 profilePicturePresignedUrl 的值 属性 需要使用服务计算。
看起来最有效的方法是在用户实体 class 中创建一个方法来注入所需的服务,如下所示:
Entity/User.php
public function __construct(FileDownloader $fileDownloader) {
$this->fileDownloader = $fileDownloader;
}
public function getProfilePicturePresignedUrl(): string
{
return $this->fileDownloader->generatePresignedUrl($this->profilePicturePath);
}
但是,我了解到在实体 classes 中注入服务被认为是不好的做法,并且在文档中找不到如何这样做的参考资料。
替代方案是在控制器中生成此值:
Controller/UserController.php
public function getUserInfo(FileDownloader $fileDownloader)
{
$user = $this->getUser();
$user->setProfilePicturePresignedUrl($fileDownloader->generatePresignedUrl($user->getProfilePicturePath()));
return $this->createResponse($user);
}
但是,有许多调用 getUser 的控制器方法,在所有方法中复制此逻辑似乎不正确...在这种情况下注入生成预签名所需的服务是否有意义URL 在实体 class 中还是有更好的替代方法?
Doctrine 实体监听器
实体侦听器定义为 PHP classes,它们侦听单个实体 class 上的单个 Doctrine 事件。例如,假设您希望在从数据库加载特定实体时准备该实体。为此,为 postLoad
Doctrine 事件定义一个侦听器。参见 documentation。
这样,在您的情况下,每次您从数据库中获取用户实体时,属性 将被初始化并准备好在您的代码中的任何地方使用。请注意,我不建议将它用于繁重的任务,因为它会显着降低您的应用性能。
src/EventListener/UserListener.php
namespace App\EventListener;
use App\Entity\User;
use App\Service\FileDownloader;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\Event\LifecycleEventArgs;
class UserListener
{
private $entityManager;
private $fileDownloader;
public function __construct(EntityManagerInterface $entityManager, FileDownloader $fileDownloader)
{
$this->entityManager = $entityManager;
$this->fileDownloader = $fileDownloader;
}
public function postLoad(User $user, LifecycleEventArgs $event): void
{
$path = $user->getProfilePicturePath();
$url = $this->fileDownloader->generatePresignedUrl($path);
$user->setProfilePicturePresignedUrl($url);
}
}
config/services.yaml
services:
App\EventListener\UserListener:
tags:
- {
name: doctrine.orm.entity_listener,
entity: 'App\Entity\User',
event: "postLoad"
}
我有一个 User 对象,它有一个 profilePicturePresignedUrl 属性。 profilePicturePresignedUrl 的值 属性 需要使用服务计算。
看起来最有效的方法是在用户实体 class 中创建一个方法来注入所需的服务,如下所示:
Entity/User.php
public function __construct(FileDownloader $fileDownloader) {
$this->fileDownloader = $fileDownloader;
}
public function getProfilePicturePresignedUrl(): string
{
return $this->fileDownloader->generatePresignedUrl($this->profilePicturePath);
}
但是,我了解到在实体 classes 中注入服务被认为是不好的做法,并且在文档中找不到如何这样做的参考资料。
替代方案是在控制器中生成此值:
Controller/UserController.php
public function getUserInfo(FileDownloader $fileDownloader)
{
$user = $this->getUser();
$user->setProfilePicturePresignedUrl($fileDownloader->generatePresignedUrl($user->getProfilePicturePath()));
return $this->createResponse($user);
}
但是,有许多调用 getUser 的控制器方法,在所有方法中复制此逻辑似乎不正确...在这种情况下注入生成预签名所需的服务是否有意义URL 在实体 class 中还是有更好的替代方法?
Doctrine 实体监听器
实体侦听器定义为 PHP classes,它们侦听单个实体 class 上的单个 Doctrine 事件。例如,假设您希望在从数据库加载特定实体时准备该实体。为此,为 postLoad
Doctrine 事件定义一个侦听器。参见 documentation。
这样,在您的情况下,每次您从数据库中获取用户实体时,属性 将被初始化并准备好在您的代码中的任何地方使用。请注意,我不建议将它用于繁重的任务,因为它会显着降低您的应用性能。
src/EventListener/UserListener.php
namespace App\EventListener;
use App\Entity\User;
use App\Service\FileDownloader;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\Event\LifecycleEventArgs;
class UserListener
{
private $entityManager;
private $fileDownloader;
public function __construct(EntityManagerInterface $entityManager, FileDownloader $fileDownloader)
{
$this->entityManager = $entityManager;
$this->fileDownloader = $fileDownloader;
}
public function postLoad(User $user, LifecycleEventArgs $event): void
{
$path = $user->getProfilePicturePath();
$url = $this->fileDownloader->generatePresignedUrl($path);
$user->setProfilePicturePresignedUrl($url);
}
}
config/services.yaml
services:
App\EventListener\UserListener:
tags:
- {
name: doctrine.orm.entity_listener,
entity: 'App\Entity\User',
event: "postLoad"
}