Doctrine UniqueConstraintViolationException

我有一个SQLite表,其中包含有关图像的数据。一列是文本字段,其中包含该图像在网站上的显示位置。该字段具有唯一的约束。以下是表定义:position


CREATE TABLE images (id INTEGER PRIMARY KEY, title TEXT UNIQUE NOT NULL, position TEXT UNIQUE

NOT NULL, caption TEXT, filename TEXT, album INTEGER NOT NULL, publicationDate TEXT, updated

TEXT, createdBy INTEGER

 NOT NULL, updatedBy INTEGER NOT NULL, FOREIGN KEY (createdBy) REFERENCES users(id), FOREIGN KEY

(album) REFERENCES albums(id), FOREIGN KEY (updatedBy) REFERENCES users(id));

并且,来自实体的相关位:


/**

* @ORM\Entity

* @ORM\Table(name="images",indexes={

*       @Index(name="publication_date", columns={"publicationDate"})},

*       uniqueConstraints={@UniqueConstraint(name="unique_position", columns={"position", "fileName"})}

*       )

*/

class Image

{

    /**

    * @ORM\Id

    * @ORM\Column(type="integer")

    * @ORM\GeneratedValue

    **/

    protected $id;


    /**

    * @ORM\Column(type="string", unique=true)

    */

    protected $position;

我可以成功地写入表(Doctrine 保留,然后刷新),除非列上有唯一的约束冲突。当存在唯一的约束冲突时,flush() 将以静默方式失败(不写入数据库),并且应用程序将继续执行。以下是相关代码 - 设置并保留实体后:position


        try {

            $this->entityManager->flush();

            $message['type'] = 'alert-info';

            $message['content'] = "$title added succesfully";

            return $message;

        } catch (UniqueConstraintViolationException $e) {

            $message['type'] = 'alert-danger';

            $message['content'] = "$title could not be added " . $e;

            return $this->create($message, $formVars);

        } catch (Exception $e) {

            $message['type'] = 'alert-danger';

            $message['content'] = "$title could not be added " . $e;

            return $this->create($message, $formVars);

        }

为什么我没有捕捉到异常?或者,它根本没有被扔掉吗?


catspeake
浏览 132回答 1
1回答

呼唤远方

发布我上面提供的代码实现提示,只需运行2次即可查看结果,这是控制器:<?phpnamespace App\Controller;use App\Entity\TestEntity;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\Routing\Annotation\Route;use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;use Symfony\Component\Validator\Validator\ValidatorInterface;class TestController extends AbstractController{&nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp;* @Route("/", name="test")&nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; public function test(Request $request, ValidatorInterface $validator)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; $newEntity = new TestEntity();&nbsp; &nbsp; &nbsp; &nbsp; $newEntity->setPosition('test');&nbsp; &nbsp; &nbsp; &nbsp; // In addition $form->isValid() does this for you and displays form error specified in entity&nbsp; &nbsp; &nbsp; &nbsp; if(($result = $validator->validate($newEntity))->count() === 0) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $em = $this->getDoctrine()->getManager();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $em->persist($newEntity);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $em->flush();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dump('Entity persisted');&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dump($result); // <- array of violations&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dump('Sorry entity with this position exists');&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; die;&nbsp; &nbsp; }}这是您的实体:<?phpnamespace App\Entity;use Doctrine\ORM\Mapping as ORM;use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;/**&nbsp;* @ORM\Table(name="test_entity")&nbsp;* @ORM\Entity(repositoryClass="App\Repository\TestEntityRepository")&nbsp;*&nbsp;&nbsp;* @UniqueEntity(&nbsp;*&nbsp; fields={"position"},&nbsp;*&nbsp; errorPath="position",&nbsp;*&nbsp; message="Duplicate of position {{ value }}."&nbsp;* )&nbsp;*/class TestEntity{&nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp;* @ORM\Column(name="id", type="integer")&nbsp; &nbsp; &nbsp;* @ORM\Id&nbsp; &nbsp; &nbsp;* @ORM\GeneratedValue(strategy="AUTO")&nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; private $id;&nbsp; &nbsp; public function getId()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return $this->id;&nbsp; &nbsp; }&nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp;* @ORM\Column(name="position", type="string", length=190, unique=true) // key length limit for Mysql&nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; private $position;&nbsp; &nbsp; public function getPosition()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return $this->position;&nbsp; &nbsp; }&nbsp; &nbsp; public function setPosition($position)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; $this->position = $position;&nbsp; &nbsp; &nbsp; &nbsp; return $this;&nbsp; &nbsp; }}出于好奇,我测试了你的第一个想法,它似乎对我有用<?phpnamespace App\Controller;use App\Entity\TestEntity;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\Routing\Annotation\Route;use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;use Symfony\Component\Validator\Validator\ValidatorInterface;class TestController extends AbstractController{&nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp;* @Route("/", name="test")&nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; public function test(Request $request, ValidatorInterface $validator)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; $newEntity = new TestEntity();&nbsp; &nbsp; &nbsp; &nbsp; $newEntity->setPosition('test');&nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $em = $this->getDoctrine()->getManager();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $em->persist($newEntity);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $em->flush();&nbsp; &nbsp; &nbsp; &nbsp; } catch(\Doctrine\DBAL\Exception\UniqueConstraintViolationException $e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dump('First catch');&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dump($e);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; catch(\Exception $e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dump('Second catch');&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dump($e);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; die;&nbsp; &nbsp; }}它导致“第一次捕获”的转储,但这可能与我使用的是mysql而不是SQlite有关,这也是对Symfony验证文档的引用,以防您想检查它EDIT2Simple Validator 类class SomeSortOfValidator{&nbsp; &nbsp; public function exists($entity, $fieldName, $fieldValue)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // Lets suppose you have entity manager autowired.&nbsp; &nbsp; &nbsp; &nbsp; $record = $this->em->getRepository($entity)->findOneBy([&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $fieldName => $fieldValue&nbsp; &nbsp; &nbsp; &nbsp; ]);&nbsp; &nbsp; &nbsp; &nbsp; return $record ? true : false;&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP