6

使用学说 2.1(和 zend 框架 1.11,这对这件事并不重要),我怎样才能进行发布持久化和发布更新操作,这涉及重新保存到数据库?

例如,根据刚刚生成的主键 id 创建唯一令牌,或者为上传的图像生成缩略图(实际上不需要重新保存到数据库,但仍然)?


编辑 - 让我们解释一下,好吗?

以上实际上是关于两种情况的问题。这两种情况都与以下状态有关:

假设我有一个User实体。当对象被标记为持久化后被刷新时,它将具有mysql的正常自动生成的ID——这意味着运行数字通常从1、2、3等开始。
每个用户都可以上传一张图片——这他将能够在应用程序中使用——该应用程序也将在数据库中记录。所以我有另一个实体叫做Image. 每个Image实体还有一个自动生成的 ID - 与用户 ID 相同的方法。

现在 - 这是场景:

  1. 当用户上传图像时,我想在该图像保存到数据库后立即为其生成缩略图。这应该发生在每个新的或更新的图像上。
    由于我们试图保持智能,我不希望生成缩略图的代码这样编写:

    $图像 = 新图像();
    ...
    $entityManager->persist($image);
    $entityManager->flush();
    callToFunctionThatGeneratesThumbnailOnImage($image);

    而是我希望它在对象的持久化(嗯,持久化对象的刷新)上自动发生,就像prePersistorpreUpdate方法一样。

  2. 由于用户上传了一张图片,他得到了一个链接。它可能看起来像:http://www.mysite.com/showImage?id=[IMAGEID].
    这允许任何人只需更改此链接中的 imageid,并查看其他用户的图像。
    所以为了防止这样的事情发生,我想为每个图像生成一个唯一的令牌。因为它真的不需要很复杂,所以我考虑过使用图像 id 的 md5 值,并加一些盐。
    但为此,我需要拥有该图像的 id——我只有在刷新持久对象后才会拥有它——然后生成 md5,然后将其再次保存到数据库中。

了解图像的链接应该是可公开访问的,因此我不能只允许经过身份验证的用户通过某种权限规则查看它们。

4

2 回答 2

7

您可能已经了解Doctrine 事件。你可以做什么:

使用postPersist事件处理程序。那一个发生在数据库插入之后,因此自动生成的 id 可用。

EventManager课程可以帮助您:

class MyEventListener
{
    public function postPersist(LifecycleEventArgs $eventArgs)
    {
        // in a listener you have the entity instance and the 
        // EntityManager available via the event arguments
        $entity = $eventArgs->getEntity();
        $em = $eventArgs->getEntityManager();

        if ($entity instanceof User) {
            // do some stuff
        }

    }
}

$eventManager = $em->getEventManager():
$eventManager->addEventListener(Events::postPersist, new MyEventListener());

请务必检查例如是否User已经有一个Image,否则如果您在事件侦听器中调用 flush ,您可能会陷入无限循环。

当然,您也可以User使用内联postPersisteventHandler 让您的类知道该图像创建操作并添加@HasLifecycleCallbacks您的映射,然后始终在请求结束时刷新,例如在关闭函数中,但在我看来,这种东西属于单独的监听器。YMMV。

如果在刷新之前需要实体 id,在创建对象之后,另一种方法是为应用程序中的实体生成 id,例如使用uuids

现在您可以执行以下操作:

class Entity {
    public function __construct()
    {
        $this->id = uuid_create();
    }
}

现在你已经设置了一个 id,当你这样做时:

$e = new Entity();

而且您只需要在请求结束时调用 EntityManager::flush

于 2011-09-12T19:34:25.770 回答
2

最后,我听了@Arms 对这个问题的评论。
我开始使用服务层来做这些事情。
所以现在,我在服务层中有一个创建图像实体的方法。在它调用persist和flush之后,它会调用生成缩略图的方法。

服务层模式是解决此类问题的好方法。

于 2012-04-17T10:05:17.933 回答