如何在生命周期内阻止学说更新我的实体

How to stop doctrine from updating my entity during is lifecycle

我正在 Symfony 2 中处理我的一个实体。如果我上传一个 zip 文件,我的实体将打开该 zip 文件,找到一个名为 _projet 的文件,然后生成一个姓名。问题是如果发生错误,我需要停止整个上传和更新过程,比如它无法打开 zip 或者找不到名为 _projet.zip 的文件。我基本上是在调整这本食谱中显示的内容:

http://symfony.com/doc/current/cookbook/doctrine/file_uploads.html

有人说:

// if there is an error when moving the file, an exception will
// be automatically thrown by move(). This will properly prevent
// the entity from being persisted to the database on error

所以如果发生不好的事情我想做同样的事情并且可能以某种方式告诉我的控制器有问题(我在我的控制器中使用 flush())

到目前为止,这是我的代码:

/**
 * @ORM\PrePersist()
 * @ORM\PreUpdate()
 */
public function preUpload()
{
    //If there is a file for the project
    if (null !== $this->getFichierFile())
    {
        //Create uniq name
        $nomFichierProjet = sha1(uniqid(mt_rand(), true));

        //Check if it's a zip
        if($this->getFichierFile()->guessExtension()=="zip")
        {
            //New zip archive
            $zip=new ZipArchive;

            //While indicate if an error happen
            $erreur=true;

            //Open the zip
            if($zip->open($formulaire['fichierFile']->getData())===TRUE)
            {
                //Loop throw file in zip
                for($i=0; $i<$zip->numFiles; $i++) 
                {
                    //If the file is named _projet
                    if(pathinfo($zip->getNameIndex($i))['filename']=="_projet")
                    {
                        //Crate the file name
                        $this->fichier=$nomFichierProjet.'.'.pathinfo($zip->getNameIndex($i))['extension'];

                        //No error
                        $erreur=false;

                        //Quit loop
                        break;
                    }
                }
            }

            //If an error happen
            if($erreur)
            {
                //Prevent persisting
            }

        }
        else
        {
            //Create file name
            $this->fichier = $nomFichierProjet.'.'.$this->getFichierFile()->guessExtension();
        }
    }
}

您可以简单地做到这一点,定义一个自定义上传异常。如果在处理上传过程中发生错误,你应该抛出它并在你的控制器中捕获它并处理错误:

因此,通过扩展基本异常来创建异常

<?php
// path/to/your/AppBundle/Exception
namespace AppBundle\Exception;

class UploadException extends \Exception{
    // Nothing special here, but you also can collect
    // more information if you want, by overriding the 
    // constructor, or use public properties or getter
    // and setter. it all up to you ;)
}

如果在处理上传过程中出现错误,请将其放入您的实体中

//in your Entity::preUpload() method
// [...]

//If an error happen
if($erreur)
{
    // Prevent persisting
    // It does not matter, which exception is thrown here, you could even
    // throw a "normal" `\Exception`, but for better error handling you
    // should use your own.
    throw new \AppBundle\Exception\UploadException('An error occourred during upload!');
}

并在您的控制器中捕获并处理它:

// in your controller
try{
    $em->persist($entity);
    $em->flush();
} catch (\AppBundle\Exception\UploadException $e){
    // Handle the upload error
    // Catching your own exception (`\AppBundle\Exception\UploadException`)
    // you are sure now that the error occurred during your upload handling.
}

编码愉快

Flush 的调用是唯一提供实体更新的东西,所以通常我会像 skroczek 那样做。如果你不想触发异常,你可以用数组来做到这一点:

$errors = array();
//zip not found
errors[] = "zip not found";
if (count($errors) == 0) {
  $em->persist($entity);
  $em->flush();
}

对你有帮助吗?