This forum is in READ-ONLY mode.
You can look around, but if you want to ask a new question, please use Stack Overflow.

[SOLVED] many-to-many

Discussion specific to symfony 1.1.x stable

[SOLVED] many-to-many

by mattthidoteu » Mon Dec 01, 2008 12:42 am

Hi,

I'm having some trouble with a many-to-many relationship

I have 3 tables :

Code: Select all
personne:
    id:                 ~
    ...

  groupe:
    id:                 ~
    ...

  groupe_personne:
    groupe_id:       { type: integer, foreignTable: groupe, foreignReference: id, primaryKey: true, onDelete: cascade }
    personne_id:     { type: integer, foreignTable: personne, foreignReference: id, primaryKey: true, onDelete: cascade }



the problem I'm having is that every time I update a Personne, if this Personne belongs to a Groupe, the corresponding entry in groupe_personne is also deleted.Which is annoying because I don't want a Personne-Groupe relationship to be deleted just because the Personne's address is edited

I found that is the log :
Code: Select all
Nov 30 22:20:51 symfony [info] {sfDebugConnection} beginning transaction.
Nov 30 22:20:51 symfony [info] {sfDebugConnection} beginning transaction.
Nov 30 22:20:51 symfony [info] {sfDebugConnection} prepareStatement(): UPDATE personne SET ADRESSE = ? WHERE personne.ID=?
Nov 30 22:20:51 symfony [info] {sfDebugConnection} executeUpdate(): UPDATE personne SET ADRESSE = 'XXX' WHERE personne.ID=2
Nov 30 22:20:51 symfony [info] {sfDebugConnection} beginning transaction.
Nov 30 22:20:51 symfony [info] {sfDebugConnection} committing transaction.
Nov 30 22:20:51 symfony [info] {sfDebugConnection} committing transaction.
Nov 30 22:20:51 symfony [info] {sfDebugConnection} beginning transaction.
Nov 30 22:20:51 symfony [info] {sfDebugConnection} prepareStatement(): DELETE FROM groupe_personne WHERE groupe_personne.PERSONNE_ID=?
Nov 30 22:20:51 symfony [info] {sfDebugConnection} executeUpdate(): DELETE FROM groupe_personne WHERE groupe_personne.PERSONNE_ID=2
Nov 30 22:20:51 symfony [info] {sfDebugConnection} committing transaction.
Nov 30 22:20:51 symfony [info] {sfDebugConnection} committing transaction.


I really don't understand where this DELETE command comes from ?

thanks,
mattthidoteu
Junior Member
 
Posts: 6
Joined: Mon Dec 01, 2008 12:30 am

Re: many-to-many

by masterix » Mon Dec 01, 2008 12:16 pm

Try to turn off "onDelete:cascade" for a while of testing and check it once again. It looks like UPDATE first deletes record from personne and then adds new one instead of really UPDATE query.

You can show us code as well.

Cheers,
masterix
masterix
Member
 
Posts: 41
Joined: Mon Sep 01, 2008 1:08 pm

Re: many-to-many

by mattthidoteu » Tue Dec 02, 2008 4:29 pm

Hi Masterix, thanks for your answer and sorry for my late reply.
I tried without the onDelete:Cascade but the problem is still there.
There's nothing fancy in the code, it's just a basic form generated with propel:generate-crud, I haven't added anything to it yet.

What I understand from the log is that after the Personne is updated, the corresponding entry in personne_groupe is deleted ... and I really don't understand why ...
mattthidoteu
Junior Member
 
Posts: 6
Joined: Mon Dec 01, 2008 12:30 am

Re: many-to-many

by masterix » Tue Dec 02, 2008 5:12 pm

It's quite interesting but for now I have no idea what's going on. Paste full schema.yml ( or part with full definitions of these three tables ) and I will try CRUD at my localhost if I have enough time.

Cheers,
masterix
masterix
Member
 
Posts: 41
Joined: Mon Sep 01, 2008 1:08 pm

Re: many-to-many

by mattthidoteu » Tue Dec 02, 2008 5:35 pm

Thanks for that Masterix, here is the schema.yml part about Personne and Groupe :

Code: Select all
  personne:
    id:                 ~
    activite:           { type: varchar(255), required: false }
    etatcivil:          { type: varchar(255), required: false }
    nom:                { type: varchar(255), required: true }
    prenom:             { type: varchar(255), required: false }
    adresse:            { type: longvarchar, required: false }
    cp:                 { type: varchar(10), required: false }
    ville:              { type: varchar(255), required: false }
    pays:               { type: varchar(255), required: false }
    tel:                { type: varchar(20), required: false }
    fax:                { type: varchar(20), required: false }
    portable:           { type: varchar(20), required: false }
    email:              { type: varchar(255), required: false }
    website:            { type: varchar(255), required: false }

  groupe:
    id:                 ~
    activite:           { type: varchar(255), required: false }
    type:               { type: varchar(255), required: false }
    nom:                { type: varchar(255), required: true }
    adresse:            { type: longvarchar, required: false }
    cp:                 { type: varchar(10), required: false }
    ville:              { type: varchar(255), required: false }
    pays:               { type: varchar(255), required: false }
    tel:                { type: varchar(20), required: false }
    fax:                { type: varchar(20), required: false }
    portable:           { type: varchar(20), required: false }
    email:              { type: varchar(255), required: false }
    website:            { type: varchar(255), required: false }

  groupe_personne:
    groupe_id:       { type: integer, foreignTable: groupe, foreignReference: id, primaryKey: true }
    personne_id:     { type: integer, foreignTable: personne, foreignReference: id, primaryKey: true }



The only thing I changed from the generate-crud code is the action.class.php :
Code: Select all
class groupeActions extends sfActions
{
   public function executeIndex()
   {
      $this->groupeList = GroupePeer::doSelect(new Criteria());
   }

   public function executeEdit($request)
   {
      $this->form = new GroupeForm(GroupePeer::retrieveByPk($request->getParameter('id')));

      if ($request->isMethod('post'))
      {
         $this->form->bind($request->getParameter('groupe'));
         if ($this->form->isValid())
         {
            $groupe = $this->form->save();

            $this->redirect('groupe/saved?id='.$groupe->getId());
         }
      }
   }

   public function executeDelete($request)
   {
      $this->forward404Unless($groupe = GroupePeer::retrieveByPk($request->getParameter('id')));

      $groupe->delete();

      $this->redirect('groupe/index');
   }
   
   public function executeSaved($request) {
      $this->id= $request->getParameter('id');
   }
}


and the savedSuccess.php file looks like that :
Code: Select all
<br /><br /><br /><br />
Enregistrement OK :
<ul>
   <li><a href="<?php echo url_for('groupe/edit') ?>">Créer nouveau</a></li>
   <li><a href="<?php echo url_for('groupe/edit?id='.$id) ?>">Modifier</a></li>
   <li><a href="<?php echo url_for('groupe/index') ?>">Retour</a></li>
</ul>


I did the same for Groupe and Personne

I'm using symfony 1.1 (rev 13636)

Thanks
mattthidoteu
Junior Member
 
Posts: 6
Joined: Mon Dec 01, 2008 12:30 am

Re: many-to-many

by drahpal » Tue Dec 09, 2008 10:28 am

Hi,

You must look into the generated base form of personne (/lib/form/base/BasePersonneForm.class.php).

you may find a saveGroupePersonneList or something, and see that the default behavior for a many to many relationship, in the sfForm, is to delete and recreate each relation.

You can do something in the doSave method I think, to disable the call (unset the field) when you want.
Drahpal
drahpal
Member
 
Posts: 40
Joined: Thu Jul 05, 2007 4:00 pm
Location: France

Re: many-to-many

by rschumacher » Tue Dec 09, 2008 12:44 pm

mattthidoteu wrote:
...the problem I'm having is that every time I update a Personne, if this Personne belongs to a Groupe, the corresponding entry in groupe_personne is also deleted.Which is annoying because I don't want a Personne-Groupe relationship to be deleted just because the Personne's address is edited...


Hi,
My $0.02€ hint/question: reading that the problem is when an PERSONNE record is being updated, however the action code provided relates to a GROUPE record...

--> could it be that you have enhanced the GroupeForm class to embed one or more PersonneForm objects?

If so, can you provide us the your GroupeForm code? Maybe also the PersonneForm code...

Cheers RAPHAEL
User avatar
rschumacher
Faithful Member
 
Posts: 231
Joined: Wed Aug 15, 2007 3:28 pm
Location: Basel, Switzerland

Re: many-to-many

by mattthidoteu » Tue Dec 09, 2008 8:57 pm

Hi,

Thanks for your answer

@rschumacher : no I didn't change anything in Groupform

@drahpal : you were right, I had no field for groupe_personne_list in my Personne form, so the relations were deleted BUT not re-created everytime I edited a Personne.

So I just unset the widget and the validator for groupe_personne_list and everything is working now :

Code: Select all
class PersonneForm extends BasePersonneForm {
   public function configure() {
      unset($this->validatorSchema['groupe_personne_list']);
      unset($this->widgetSchema['groupe_personne_list']);
   }
}


thanks!
mattthidoteu
Junior Member
 
Posts: 6
Joined: Mon Dec 01, 2008 12:30 am

Re: [SOLVED] many-to-many

by onip » Fri Dec 30, 2011 8:16 pm

I'm having this same problem in 1.4 so:
1) you saved my day, so very thanks
2) is it confirmed that this is "the" way to avoid this kind of behaviour?

I don't want that anytime an user updates an entity he owns every link this entity has with Comment (by other users) through a EntityComment table gets dropped.
onip
Junior Member
 
Posts: 2
Joined: Tue May 18, 2010 3:11 pm
Location: Parma, Italy