Salut à tous,

j'utilise SonataAdminBundle. Mon but est d'administrer mes Articles de mon site et ainsi de permettre aux administrateurs d'en créer au travers l'interface d'administration.

Voici comment la relation est définis:

J'ai donc dans user:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 
    /**
    * @var articles
    *
    * Ici on va créé la relation OneToMany (Many: article to One 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;
    }
 
 
   /**
    * Méthode qui permet d'ajouter un article à notre utilisateur. On va ainsi respecter le DRY
    * en indiquant l'utilisateur qui poste l'article
    *
    * @param $unArticle
    */
    public function addArticle(\Kark\RecetteBundle\Entity\Article $unArticle)
    {
        $this->articles[] = $unArticle;
        $unArticle->setUser($this);
    }






Et voici dans ma classe Article:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  /**
    *      @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;
    }



Dans mon SonataAdminBundle, j'ai alors définis le constroller CRUD des deux entités User et Article:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?php
 
namespace Kark\AdminBundle\Controller;
 
use Sonata\AdminBundle\Controller\CRUDController as Controller;
 
class ArticleAdminController extends Controller
{
 
}
Voici le CRUD de User:
 
<?php
 
namespace Kark\AdminBundle\Controller;
 
use Sonata\AdminBundle\Controller\CRUDController as Controller;
 
class UserAdminController extends Controller
{
 
}
 
 
 
 
ainsi que leurs configurations dans le 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
Voici la partie pour l'entité User:

    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


Tout est bien configuré, et j'ai ainsi la définition suivante dans ma classe Admin de mon Article:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
<?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);
    }
}

Cependant, l'article ne s'insère pas puisque ce dernier réalise une INSERTION et un UPDATE, et que dans la table 'article_audit' il réalise deux fois la même insertion, et ainsi il y a un dupliquata de clé primaire...

[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'
Voici le fichier log:


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



J'ai essayer d'insérer de manière plus traditionnel, c'est-à-dire avec une action dans mon ArticleController dont voici:


Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
 
 public function ajouterNewsAction($_local)
  {
      //Toute les création ce feront au travers de formulaire
      $monArticle = new Article();
 
      //On créé notre formulaire en utilisant une classe externe
      $monFormulaire = $this->createForm(new ArticleType, $monArticle);                    
 
    //On récupère la requête
    $request = $this->get('request');
 
    //Lors de l'envoie d'un formulaire, on le réalise au travers de transfert de données de page à page via une méthode 
    //appelé POST. Ainsi on va vérifier lors de l'appel de cette fonction si cette méthode est effective, si c'est le cas c'est
    //que des données on été transmise via un formulaire de données.
    if($this->get('request')->getMethod() == 'POST')
    {
      //Traitement des données ici on va hydrater notre formulaire avec ce qui a été saisie en récupérant les valeurs 
      //de mes superglobal $_POST via une fonction plutôt rapide 
      $monFormulaire->bind($request);
 
      //On vérifie que les valeurs entrées soient correct. La validation des objets se fait via les annotation
      //de notre classe Constraints via notre Validator aliasé @Assert.
      if($monFormulaire->isValid())
      {
 
 
        //Si l'article est effectivement ajouter, c'est que tout est bon alors on créé un Tag
        $this->get('session')->getFlashBag()->add('AjoutRealise', 'L\'article a été rajouté avec succès');
 
 
        //On récupère l'utilistaeur en cours
        $user = $this->getUser();
 
        //On persist alors notre entité hydratée par le formulaire
        $entity_manager = $this->getDoctrine()->getManager();
 
        //On récupère le service de management des utilisateur du FOSUB
        $userManager = $this->get('fos_user.user_manager');
 
 
        //On ajoute notre utilisateur à notre article
        $user->addArticle($monArticle);
        $userManager->updateUser($user);
 
        $entity_manager->flush();
 
        //On redirige vers la page d'affichage de l'article
        return $this->redirect($this->generateUrl('karkrecette_voir_article', array("id" => $monArticle->getId(), "slugTitre" => $monArticle->getSlugTitre() ))); 
    }
  }
 
  //Si on est pas en présence d'une méthde get, c'est que le formulaire n'est pas encore envoyer, il est alors vierge
  //Sinon il se peut que le formulaire ne soit pas valide, on affiche alors le formulaire hydrater des valeur précédement saisie
  return $this->render('KarkRecetteBundle:Article:ajouter.html.twig', array("form" => $monFormulaire->createView(), "langue" => $_local));
  }
ET j'ai également la même erreur:

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 ["552", "UPD", 49, 1, 49, "2014-06-17 10:17:29", "qosdkqlmsdkqsmldkqsdmlqsdqlmsd", "qlmskdsqmldkqsmldqskdmlqskdsqmldkqsmdlqskdmlqsdkqsmldqskd qlskdqslmdqsd", 0, "2014-06-17 10:17:52", "qosdkqlmsdkqsmldkqsdmlqsdqlmsd"]:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '49-552' for key 'PRIMARY'
Voici le LOG qui reste toujours le même, un UPDATE après mon INSERT:

DEBUG - "START TRANSACTION"
DEBUG - INSERT INTO image_article (url, alt, extension) VALUES (?, ?, ?)
DEBUG - INSERT INTO revisions (timestamp, username) VALUES (?, ?)
DEBUG - INSERT INTO image_article_audit (rev, revtype, id, url, alt, extension) VALUES (?, ?, ?, ?, ?, ?)
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 Doctrine\DBAL\Exception\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 ["552", "UPD", 49, 1, 49, "2014-06-17 10:17:29", "qosdkqlmsdkqsmldkqsdmlqsdqlmsd", "qlmskdsqmldkqsmldqskdmlqskdsqmldkqsmdlqskdmlqsdkqsmldqskd qlskdqslmdqsd", 0, "2014-06-17 10:17:52", "qosdkqlmsdkqsmldkqsdmlqsdqlmsd"]: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '49-552' for key 'PRIMARY'" at /var/www/recette-etudiant/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php line 65
A mon humble avis, il doit y avoir un flush et un update exécuter l'un après l'autre...ou un comflit entre ORM...cependant je n'en utilise qu'un seul....



Aurais-je loupé une étape oO


Merci