【问题标题】:Symfony2 - SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry - SonataAdminBundle - UPDATE after INSERTSymfony2 - SQLSTATE [23000]:完整性约束违规:1062 重复条目 - SonataAdminBundle - 插入后更新
【发布时间】:2014-07-05 07:36:24
【问题描述】:

我使用 SonataAdminBundle。我的目标是管理我的文章,因此允许管理员通过管理界面创建文章。

这是在我的 User 类中定义关系的方式。

所以我必须使用:

     /**
    * @var articles
    *
    * Here we will set the OneToMany relationship (Many: One - article : user) 
    * @ORM\OneToMany(targetEntity="Kark\RecetteBundle\Entity\Article", mappedBy="user", cascade={"persist", "remove"})
    */
    protected $articles;

    public function __construct()
    {
        //Une classe à pour instrctruction dans sont constructeur, le constructeur du parent
        parent::__construct();

        $this->articles = new \Doctrine\Common\Collections\ArrayCollection();
    }

   /**
    * Get articles
    *
    * @return ArrayCollection
    */
    public function getArticles()
    {
        return 

$articles;
    }


   /**        
    *
    * @param $unArticle
    */
    public function addArticle(\Kark\RecetteBundle\Entity\Article $unArticle)
    {
        $this->articles[] = $unArticle;
        $unArticle->setUser($this);
    }

在我的课堂文章中:

/**
  *      @ORM\ManyToOne(targetEntity="Kark\UserBundle\Entity\User", inversedBy="articles")
  */
  private $user;

/**
 * Set user
 *
 * @param User
 * @return article
 */
 public function setUser(\Kark\UserBundle\Entity\User $unUser)
 {
    $this->user = $unUser;

    return $this;
 }

 /**
 * Get user
 *
 * @return User
 */
  public function getUser()
  {
     return $this->user;
  }

在我的 SonataAdminBundle 中,我随后定义了控制器 CRUD 两个实体用户和文章:

    namespace Kark\AdminBundle\Controller;

    use Sonata\AdminBundle\Controller\CRUDController as Controller;

    class ArticleAdminController extends Controller
    {

    }

这里是 CRUD 用户:

<?php

namespace Kark\AdminBundle\Controller;

use Sonata\AdminBundle\Controller\CRUDController as Controller;

class UserAdminController extends Controller
{

}

及其在 admin.cfg 中的配置:

# Kark/AdminBundle/Resources/config/admin.yml
services:
    kark.admin.admin.article:
        class: Kark\AdminBundle\Admin\ArticleAdmin
        tags:
            - { name: sonata.admin, manager_type: orm, group: Article, label: articles }
        arguments:
            - ~
            - Kark\RecetteBundle\Entity\Article
            - KarkAdminBundle:ArticleAdmin

这是用户实体的部分:

kark.admin.admin.userarticle:
    class: Kark\AdminBundle\Admin\UserAdmin
    tags:
        - { name: sonata.admin, manager_type: orm, group: user, label: users }
    arguments:
        - ~
        - Kark\UserBundle\Entity\User
        - KarkAdminBundle:UserAdmin

一切都设置好了,我在我的文章管理类中有以下定义:

<?php

namespace Kark\AdminBundle\Admin;

use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use Kark\RecetteBundle\Entity\Article;
use Kark\RecetteBundle\Entity\ImageArticle;

use Knp\Menu\ItemInterface as MenuItemInterface;

class ArticleAdmin extends Admin
{
     // setup the default sort column and order
    protected $datagridValues = array(
        '_sort_order' => 'ASC',
        '_sort_by' => 'name'
    );


    // L'ensemble des champs qui seront montrer lors de la création ou de la modification d'une entité
    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper
            ->with('General')
                ->add('titre', 'text')
                ->add('imageArticle', 'sonata_type_admin', array('delete' => false), array('required' => true, 'edit' => 'inline'))
                ->add('contenu','textarea');
     }

    /**
    *
    * Fonction qui va permettre d'afficher les différent filtres de recherche dans notre tableau
    * de notre interface.
    *
    */
    protected function configureDatagridFilters(DatagridMapper $datagridMapper)
    {
        $datagridMapper
            ->add('titre')
            ->add('user.username')
        ;
    }

    /**
    * Fonction qui redéfini celle de la classe mère Admin. Cette fonction va nous permettre de préciser les
    * champs qui seront affiché dans notre tableau lorsque l'on listera nos entités
    */
    protected function configureListFields(ListMapper $listMapper)
    {
        $listMapper
            ->addIdentifier('titre')
            ->add('date', null, array('route' => array('name' => 'show')))
            ->add('contenu')
            ->add('user.username')
            ->add('_action', 'actions', array(
                'actions' => array(
                'show' => array(),
                'edit' => array(),
                'delete' => array()
                )
            ))
        ;
    }

    /**
    * Fonction qui redéfinie la fonction de la classe mère qui permet d'indiquer les champs qui seront affiché
    * lorsque l'on consultera un article
    */
    protected function configureShowFields(ShowMapper $showMapper)
    {
        $showMapper
            ->add('date')
            ->add('titre')
            ->add('contenu')
            ->add('imageArticle.getWebPath()', 'string', array('template' => 'KarkAdminBundle:ArticleAdmin:list_image.html.twig'))
            ->add('user.username')
        ;
    }


 /**
     * {@inheritdoc}
     */
    public function prePersist($object)
    {

        $user = $this->getConfigurationPool()->getContainer()->get('security.context')->getToken()->getUser();
        $user->addArticle($object);
    }

    /**
     * {@inheritdoc}
     */
    public function preUpdate($object)
    {
        $user = $this->getConfigurationPool()->getContainer()->get('security.context')->getToken()->getUser();
        $user->addArticle($object);
    }
}

但是,文章没有插入,因为它执行了 INSERT 和 UPDATE,并且在表 'article_audit 中它执行了两次相同的插入,因此有一个主键 dupliquata ...

[3/4] UniqueConstraintViolationException: An exception occurred while executing 'INSERT INTO article_audit (rev, revtype, imageArticle_id, user_id, id, date, titre, contenu, publication, dateEdition, slugTitre) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' with params ["545", "UPD", 43, 1, 43, "2014-06-16 23:28:40", "qsmodjqskdjqslkdqjsk", "<p>qsldkqsmldkqslmdkqsmdlqslk lmqskdmlqskdqsmld qskdjqslkdqjsldqksd<\/p>", 0, "2014-06-16 23:28:40", "qsmodjqskdjqslkdqjsk"]:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '43-545' for key 'PRIMARY'

 PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '43-545' for key 'PRIMARY'

这是日志文件:

DEBUG - INSERT INTO article (date, titre, contenu, publication, dateEdition, slugTitre, imageArticle_id, user_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
DEBUG - INSERT INTO article_audit (rev, revtype, imageArticle_id, user_id, id, date, titre, contenu, publication, dateEdition, slugTitre) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
DEBUG - UPDATE article SET date = ?, titre = ?, contenu = ?, publication = ?, dateEdition = ?, slugTitre = ?, imageArticle_id = ?, user_id = ? WHERE id = ?
DEBUG - INSERT INTO article_audit (rev, revtype, imageArticle_id, user_id, id, date, titre, contenu, publication, dateEdition, slugTitre) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
DEBUG - "ROLLBACK"
CRITICAL - Uncaught PHP Exception Sonata\AdminBundle\Exception\ModelManagerException: "Failed to create object: Kark\RecetteBundle\Entity\Article" at /var/www/recette-etudiant/vendor/sonata-project/doctrine-orm-admin-bundle/Model/ModelManager.php line 142

更新 -

我尝试插入传统方式,也就是说,在我的 ArticleController 中使用一个动作,内容如下:

公共函数 ajouterNewsAction($_local) { // 整个创作都会通过这个表单 $monArticle = new Article();

         // We create our form using an external class 
         $monFormulaire = $this->createForm(new ArticleType, $monArticle);                   

       // Query is recovered 
       $request = $this->get('request');

         // When sending a form, it is realized through transfer data from page to page via a method 
    //called POST. So we'll check when calling this function if this method is effective, if the case is 
    //data that have been transmitted via a data form. 
       if($this->get('request')->getMethod() == 'POST')
       {
         // Process the data here we will moisturize our form with what was before retrieving values 
      // my $ _POST superglobal via a rather fast function
         $monFormulaire->bind($request);

         // Check that the values ​​entered are correct. Validation objects is via annotation 
      // Constraints our class Validator aliased via our @ Assert. 
         if($monFormulaire->isValid())
         {


            // If the item is actually add is that everything is good then created a Tag 
           $this->get('session')->getFlashBag()->add('AjoutRealise', 'L\'article a été rajouté avec succès');


            // Get the current utilistaeur 
           $user = $this->getUser();

           // We persist then our body hydrated by Form 
           $entity_manager = $this->getDoctrine()->getManager();

           // Get the service management of user FOSUserBundle
           $userManager = $this->get('fos_user.user_manager');


           //We add a user to our article
           $user->addArticle($monArticle);
           $userManager->updateUser($user);

           $entity_manager->flush();

           //We redirect to the page display section 
           return $this->redirect($this->generateUrl('karkrecette_voir_article', array("id" => $monArticle->getId(), "slugTitre" => $monArticle->getSlugTitre() )));
       }
     }

     // If we're not in the presence of a méthde get is that the form is not sent, then it is blank 
//Otherwise it is possible that the form is not valid, it displays the form hydrating value previously entered 
     return $this->render('KarkRecetteBundle:Article:ajouter.html.twig', array("form" => $monFormulaire->createView(), "langue" => $_local));
     }

如果我在 admin.yml 中删除为我的 Article 类管理定义的服务, 他们没有问题,因为 SonataAdmin 没有被解雇。但我真的需要管理我的文章对象。

谢谢。

【问题讨论】:

    标签: php sql symfony doctrine sonata-admin


    【解决方案1】:

    问题出在您的用户类中:

    /**        
    *
    * @param $unArticle
    */
    public function addArticle(\Kark\RecetteBundle\Entity\Article $unArticle)
    {
        $this->articles[] = $unArticle;
        $unArticle->setUser($this);
    }
    

    应该是这样的

    /**        
    *
    * @param $unArticle
    */
    public function addArticle(\Kark\RecetteBundle\Entity\Article $unArticle)
    {
        $this->articles[] = $unArticle;
    }
    

    因为您在 User 和 Article 之间映射了一对多关系,并且根据您在 User 类中的上述代码,它违反了完整性约束,因为它基本上尝试为一篇文章设置多个用户..

    【讨论】:

    • 您好,谢谢!我尝试了这个,但是 article_audit 总是尝试插入而没有成功,因为插入后的更新总是被触发,在这里我认为这就像对一篇文章有​​很多评论:每篇文章都针对一个用户,所以用户有很多文章。您所说的是多对多关系:许多用户对许多文章,因此一篇文章可能有许多用户,或者 ManyTOOne 但许多用户对一篇文章。这不是我做的。
    • 在我的例子中:一个用户有很多文章,所以我的 User 类中有一个 ArrayList 包含每个用户的文章,这就是我写这行的原因:我把我的用户放在 setter 中的文章addArticle 为了不要重复我自己,否则我会在 ArticleController 中这样做: $user->addArticle($monArticle); $monArticle->setUser($user);但我什至尝试这样做,但总是触发此更新。\n 在我的数据库中,我们可以在每个针对用户的文章中看到一个外键“user_id”。这就是我定义的 OneToMany。
    【解决方案2】:

    当我在 composer.json 中将 Symfony 2.3 更新为 2.6@dev 时,我解决了我的问题。当然,这只是一个内部问题。

    【讨论】:

      猜你喜欢
      • 2016-05-23
      • 1970-01-01
      • 2016-01-16
      • 2014-09-16
      • 2018-06-06
      • 2020-12-20
      • 2016-03-10
      • 2015-03-31
      • 2019-09-12
      相关资源
      最近更新 更多