Symfony2: Télécharger le fichier via Doctrine ne se déclenche pas le cycle de vie événement PrePersist / PreUpdate

StackOverflow https://stackoverflow.com/questions/7307823

  •  26-10-2019
  •  | 
  •  

Question

j'ai essayé de mettre en œuvre le téléchargement de fichiers via callbacks doctrine / cycle de vie tel que décrit ici:

http://symfony.com/doc/ courant / livre de cuisine / doctrine / file_uploads.html # en utilisant le cycle de vie- callbacks

Jusqu'à présent, cela fonctionne, mais l'événement PrePersist / PreUpdate ne se déclenche pas, la fonction « preUpload » est pas appelé. Des fonctions telles que « télécharger » et « removeUpload » déclenchée par d'autres événements du cycle de vie sont appelés correctement.

Est-ce que quelqu'un a une idée pourquoi l'événement ne se déclenche pas ou une solution à ce problème?

Merci

Était-ce utile?

Autres conseils

J'ai une autre solution à ce problème:

Mon entité a un champ « updatedAt » qui est un horodatage de la dernière mise à jour. Puisque ce champ se prépare de toute façon (par l'extension timestampable de Gedmo) Je viens d'utiliser ce champ pour la doctrine de la ruse à croire que le entitiy a été mis à jour. Avant que je persévère l'entité que je mets ce domaine faire manuellement

if( $editForm['file']->getData() )
    $entity->setUpdateAt(new \DateTime());

De cette façon, l'entité se persistait (parce qu'elle a changé) et les fonctions PreUpdate et postUpdate sont appelés correctement. Bien sûr, cela ne fonctionne que si votre entité a un champ que vous pouvez exploiter comme ça.

il y a une solution beaucoup plus simple par rapport à l'évolution des politiques de suivi et d'autres solutions:

dans le contrôleur:

if ($form->isValid()) {
    ...
    if ($form->get('file')->getData() != NULL) {//user have uploaded a new file
        $file = $form->get('file')->getData();//get 'UploadedFile' object
        $news->setPath($file->getClientOriginalName());//change field that holds file's path in db to a temporary value,i.e original file name uploaded by user
    }
    ...
}

De cette façon vous avez changé un champ persistant (ici, il est champ de chemin), donc PreUpdate () et PostUpdate () sont déclenchées alors vous devez changer la valeur du champ de chemin à une chose que vous aimez (ie horodatage) en fonction PreUpdate () donc à la fin valeur correcte est conservée à DB.

Une astuce pourrait être de modifier l'entité, peu importe postLoad what..on.


1 Créer un champ updatedAt.

/**
 * Date/Time of the update
 *
 * @var \Datetime
 * @ORM\Column(name="updated_at", type="datetime")
 */
private $updatedAt;

2 Créer une fonction postLoad() qui modifiera votre entité de toute façon:

/**
 * @ORM\PostLoad()
 */
public function postLoad()
{
    $this->updatedAt = new \DateTime();
}

3 Juste mise à jour correctement sur le terrain PrePersist:

/**
 * @ORM\PrePersist()
 * @ORM\PreUpdate()
 */
public function preUpload()
{
    $this->updatedAt = new \DateTime();
    //...update your picture
}

Ceci est essentiellement une légère variation de la réponse de @ philipphoffmann: Ce que je fais est que je modifie un attribut avant persistant pour déclencher l'événement PreUpdate, puis-je annuler cette modification dans l'auditeur:

$entity->setToken($entity->getToken()."_tmp");
$em->flush();

Dans mon auditeur:

public function preUpdate(LifecycleEventArgs $args)
{
    $entity = $args->getEntity();

    if ($entity instanceof MyEntity) {
      $entity->setToken(str_replace('_tmp', '', $entity->getToken()));
      //...
    }
}

Une autre option consiste à afficher le champ de base de données où le nom de fichier est stocké comme un champ d'entrée caché et lorsque l'entrée de téléchargement de fichiers changements inscrits que pour vider il finit par déclencher des événements de mise à jour de la doctrine. Ainsi, sous la forme constructeur que vous pourriez avoir quelque chose comme ceci:

->add('path', 'text', array('required' => false,'label' => 'Photo file name', 'attr' => array('class' => 'invisible')))
 ->add('file', 'file', array('label' => 'Photo', 'attr' => array('class' => 'uploader','data-target' => 'iddp_rorschachbundle_institutiontype_path')))

Chemin est une propriété gérée par la doctrine (égale au nom de champ dans la table db) et le fichier est la propriété virtuelle pour gérer le téléchargement (non géré par la doctrine). La classe définit simplement l'css affichage sans pareil. Et puis un simple js pour changer la valeur du champ de saisie caché

$('.uploader').change(function(){
        var t = $(this).attr('data-target');
        //clear input value
        $("#"+t).val('');
 });

Pour moi, cela a fonctionné bien quand je viens d'appeler manuellement ces méthodes dans le contrôleur.

Avez-vous vérifié votre option de pilote de cache de métadonnées dans le fichier config.yml
Si elle existe, essayez de commenter cette ligne:

metadata_cache_driver: whateverTheStorage

Comme ceci:

#metadata_cache_driver: whateverTheStorage
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top