Как мне выполнить действия по сохранению / обновлению после публикации в доктрине 2.1, которые включают повторное сохранение в БД? - PullRequest
6 голосов
/ 12 сентября 2011

Используя доктрину 2.1 (и Zend Framework 1.11, а не то, что это имеет значение для этого вопроса), как я могу выполнить действия после сохранения и обновления после обновления, которые включают повторное сохранение в БД?

Например,создать уникальный токен на основе только что сгенерированного идентификатора первичного ключа или создать миниатюру для загруженного изображения (которое фактически не требует повторного сохранения в БД, но все же)?


РЕДАКТИРОВАТЬ - давайте объясним, не так ли?

Выше на самом деле вопрос о двух сценариях.Оба сценария относятся к следующему состоянию:

Допустим, у меня есть User сущность.Когда объект сбрасывается после того, как он был помечен как сохраняемый, у него будет обычный автоматически сгенерированный идентификатор mysql - это означает, что бегущие числа обычно начинаются с 1, 2, 3 и т. Д.
Каждый пользователь может загрузитьизображение - которое он сможет использовать в приложении - которое также будет иметь запись в БД.Итак, у меня есть другая сущность под названием Image.Каждая сущность Image также имеет автоматически сгенерированный идентификатор - та же методология, что и для идентификатора пользователя.

Сейчас - вот сценарии:

  1. Когда пользователь загружает изображение, я хочу создать эскиз для этого изображения сразу после его сохранения в БД.Это должно происходить для каждого нового или обновленного изображения.
    Поскольку мы стараемся быть умными, я не хочу, чтобы код генерировал миниатюру, которая будет написана так:

    $ image= new Image ();
    ...
    $ entityManager-> persist ($ image);
    $ entityManager-> flush ();
    callToFunctionThatGeneratesThumbnailOnImage ($ image);

    а я хочу, чтобы это происходило автоматически при сохранении объекта (ну, очистка сохраняемого объекта), как методы prePersist или preUpdate.

  2. Поскольку пользователь загрузил изображение, он получает ссылку на него.Вероятно, это будет выглядеть примерно так: http://www.mysite.com/showImage?id=[IMAGEID].
    Это позволяет любому просто изменить imageid в этой ссылке и увидеть изображения других пользователей.
    Поэтому, чтобы предотвратить такую ​​вещь, я хочу создать уникальныймаркер для каждого изображения.Так как он не должен быть сложным, я подумал об использовании значения md5 идентификатора изображения с некоторой солью.
    Но для этого мне нужно иметь идентификатор этого изображения - который я буду иметь толькопосле очистки сохраняемого объекта - затем сгенерируйте md5, а затем снова сохраните его в БД.

Поймите, что ссылки на изображения должны быть общедоступными, поэтому я не могупросто разрешите аутентифицированному пользователю просматривать их по каким-то правилам разрешения.

Ответы [ 2 ]

7 голосов
/ 12 сентября 2011

Вы, наверное, уже знаете о доктринальных событиях .Что вы можете сделать:

Использовать обработчик событий postPersist.Это происходит после вставки БД, поэтому автоматически генерируемые идентификаторы доступны.

Класс 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());

Обязательно проверьте, например, *У 1012 * уже есть Image, в противном случае, если вы вызовете flush в прослушивателе событий, вы можете оказаться в бесконечном цикле.

Конечно, вы также можете сообщить своему классу User о создании этого образаработать со встроенным postPersist eventHandler и добавлять @HasLifecycleCallbacks в ваше отображение, а затем всегда сбрасывать в конце запроса, например, в функции завершения работы, но, на мой взгляд, этот вид вещей принадлежит отдельному слушателю.YMMV.

Если вам нужен идентификатор объекта перед сбросом, сразу после создания объекта, другой подход заключается в создании идентификаторов для объектов в вашем приложении, например, с использованием uuids .

Теперь вы можете сделать что-то вроде:

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

Теперь у вас уже установлен идентификатор, когда вы просто делаете:

$e = new Entity();

И вам нужно всего лишь вызвать EntityManager :: flush наконец запроса

2 голосов
/ 17 апреля 2012

В конце концов, я слушал @Arms, который прокомментировал вопрос.
Я начал использовать сервисный слой для таких вещей.
Итак, теперь у меня есть метод в сервисном слое, который создает объект Image. После вызова persist и flush он вызывает метод, генерирующий миниатюру.

Шаблон Service Layer является хорошим решением для таких вещей.

...