title: Symfony Generator Forms, Doctrine, and M:N Relationships
body: <p>I have a basic M:N setup with three tables: candidate, position, and candidate_position.</p>
  
  <p>Here's a screenshot of the ERD from MySQL Workbench</p>
  
  <p><img src="https://i.stack.imgur.com/L3LuZ.png" alt="http://dl.dropbox.com/u/180411/stackoverflow/erd.png"></p>
  
  <p>Now, moving on from that let's talk about forms.  In the default world of symfony generator, you'd have a separate CRUD interface for all three of these tables. However, I don't want to have a CRUD interface for <code>candidate_position</code>.  </p>
  
  <p>What I want, is for the create and edit actions of the Candidate interface to contain a multi-choice field (select list, checkbox array, whatever) that would create the CandidatePosition records as part of the Candidate actions.</p>
  
  <p>On to the code</p>
  
  <p><strong>config/doctrine/schema.yml</strong> <em>(Note: the is not the entire schema.yml, but only the tables discussed here)</em></p>
  
  <pre><code>---
  detect_relations: true
  options:
    type: InnoDB
  
  candidate:
    columns:
      id:
        type: integer(4)
        primary: true
        unsigned: true
        notnull: true
        autoincrement: true
      first_name:
        type: string(45)
        notnull: true
      last_name:
        type: string(45)
        notnull: true
      created_at:
        type: integer(4)
        unsigned: true
    relations:
      Positions:
        class: Position
        refClass: CandidatePosition
        local: candidate_id
        foreign: position_id
  
  position:
    columns:
      id:
        type: integer(4)
        primary: true
        unsigned: true
        notnull: true
        autoincrement: true
      name:
        type: string(45)
    relations:
      Candidates:
        class: Candidate
        refClass: CandidatePosition
        local: position_id
        foreign: candidate_id
  
  
  candidatePosition:
    tableName: candidate_position
    columns:
      candidate_id:
        type: integer(4)
        primary: true
        unsigned: true
        notnull: true
      position_id:
        type: integer(4)
        primary: true
        unsigned: true
        notnull: true
    indexes:
      fk_candidate_position_candidate1:
        fields: [candidate_id]
      fk_candidate_position_position1:
        fields: [position_id]
  </code></pre>
  
  <p><strong>apps/backend/modules/candidate/config/generator.yml</strong></p>
  
  <pre><code>generator:
    class: sfDoctrineGenerator
    param:
      model_class:           Candidate
      theme:                 admin
      non_verbose_templates: true
      with_show:             false
      singular:              ~
      plural:                ~
      route_prefix:          candidate
      with_doctrine_route:   true
      actions_base_class:    sfActions
  
      config:
        actions: ~
        fields:  
          first_name: { label: First Name }
          last_name:  { label: Last Name }
          created_at: { label: Created On }
          candidate_positions:  {label: Positions}
        list:    
          sort:  [last_name, asc]
        filter:  ~
        form:    
          display:
            "User": [first_name, last_name]
            "Applying For": [candidate_positions]
          fields :
            hide:  [created_at]
        edit:    ~
        new:     ~
  </code></pre>
  
  <p><strong>lib/form/doctrine/candidateForm.class.php</strong></p>
  
  <pre><code>class candidateForm extends BasecandidateForm
  {
    public function configure()
    {
      unset( $this['created_at'] );
  
      $this-&gt;widgetSchema['candidate_positions'] = new sfWidgetFormDoctrineChoice(
        array( 'multiple' =&gt; true, 'model' =&gt; 'Position', 'renderer_class' =&gt; 'sfWidgetFormSelectCheckbox' )
      );
  
      $this-&gt;validatorSchema['candidate_positions'] = new sfValidatorDoctrineChoice(
        array( 'multiple' =&gt; true, 'model' =&gt; 'Position', 'min' =&gt; 1 )
      );
    }
  }
  </code></pre>
  
  <p>This all works, except when it comes to actually saving the data.  This is the point where I get stuck.</p>
  
  <p>I clearly need to do <em>something</em> to create/edit/delete the CandidatePosition records, but I'm not sure where to start working.  In <code>candidateActions</code>? Override <code>Basecandidate::save()</code>?</p>
  
  <p>Let me know if there's any other data you might need to see.</p>
  
  <ul>
  <li>PHP 5.2.x</li>
  <li>symfony 1.4.3</li>
  </ul>