Symfony 1.4 doctrine - many-to-many relationship with extra field in intermediate table

笑着哭i 提交于 2020-01-14 02:48:27

问题


There are 3 tables: shelf, section and shelf_has_section intermediate table to support n-m relation. The schema build from symfony doctrine:build-schema looks as following.

Simply,

shelf(id, position)
section(id, name)
shelf_has_section(shelf_id, section_id, number_of_books)

The schema.

Shelf:
  connection: doctrine
  tableName: shelf
  columns:
    id:
      type: integer(4)
      fixed: false
      unsigned: true
      primary: true
      autoincrement: true
    position:
      type: string(255)
      primary: false
      notnull: true
      autoincrement: false
  relations:
    ShelfHasSection:
      local: id
      foreign: shelf_id
      type: many

Section:
  connection: doctrine
  tableName: section
  columns:
    id:
      type: integer(1)
      primary: true
      autoincrement: false
    name:
      type: string(20)
      primary: false
      notnull: true
  relations:
    ShelfHasSection:
      local: id
      foreign: section_id
      type: many

ShelfHasSection:
  connection: doctrine
  tableName: shelf_has_section
  columns:
    shelf_id:
      type: integer(4)
      primary: true
      autoincrement: false
    section_id:
      type: integer(1)
      primary: true
      autoincrement: false
    number_of_books:
      type: integer(4)
      primary: false
      notnull: false
      autoincrement: false
  relations:
    Shelf:
      local: shelf_id
      foreign: id
      type: one
    Section:
      local: section_id
      foreign: id
      type: one

I managed to show Sections as a check box list through adding the following relation to Shelf in the schema. I also need to display a text field infront of section check box in order to enter number of books.

Sections:
  class: Section
  refClass: ShelfHasSection
  local: shelf_id

Simply it's like checking the list of checkboxes for available sections and add the number of books for section checked.

I tried to make it through embedRelation() etc, but lack of my symfony knowledge doesn't get me there. Any help highly appreciated.


回答1:


Theoretically speaking, if an n-m relation table has it own field, it becomes an entity itself, so the doctrine model for n-m relation doesn't match this problem... but: - First, you must to redefine your schema to add foreignAliases to n-m entity:

ShelfHasSection:
  connection: doctrine
  tableName: shelf_has_section
  columns:
    shelf_id:
      type: integer(4)
      primary: true
      autoincrement: false
    section_id:
      type: integer(1)
      primary: true
      autoincrement: false
    number_of_books:
      type: integer(4)
      primary: false
      notnull: false
      autoincrement: false
  relations:
    Shelf:
      local: shelf_id
      foreign: id
      type: one
      **foreignAlias: ShelfHasSections**
    Section:
      local: section_id
      foreign: id
      type: one
      **foreignAlias: ShelfHasSections**

If your are trying to make it work on a generated module, your checkboxes idea has no solution. I'll suggest you to use the ahDoctrineEasyEmbeddedRelationsPlugin, and embed the relation ShelfHasSections to your shelf form. The ShelfHasSectionForm embed by the plugin may have an autocomplete field for the section, and the input for the number of books. So, when you want to relate some shelf to one section, add one form (using the plugin) and select the values. The latest problem become on how to avoid duplicate sections.... I guess you should apply some javascript filter to remember witch section are already related and send it with the autocomplete query, so the doctrine query could exclude this sections.... Sounds very nasty, and it is, but it's the only one solution I can figure out.

If you not using a generator, but some custom actions/template, I guess the problem become easier: Embed 1 CustomShelfHasSectionForm to your Shelf Form (one for each section). Then, add one checkbox widget (maybe with sfWidgetFormInputCheckbox) it each form to select the relation or not. Them, processing the form remove those embedded form wich no checkbox selected. Somethig like:

class CustomShelfHasSectionForm extends ShelfHasSectionForm {
 public function configure() {
   unset($this['shelf_id']);
   $this->widgetSchema['selected'] = new sfWidgetFormInputCheckbox();
   $this->validatorSchema['selected'] = new sfValidatorBoolean(array('required' => false));
 }

}

class CustomShelfForm extends ShelfForm {
  private $unselected_sections = array();
  public function configure() {

    $sections = Doctrine::getTable('Section')->findAll();
    foreach($sections as $section) {
      $shelfHasSection = new ShelfHasSection();
      $shelfHasSection->setShefl($this->getObject());
      $shelfHasSection->setSection($section);
      $this->embedForm('section_'.$section->getId(), new CustonShelfHasSectionForm($shelfHasSection));
    }

  }


  public function doBind(array $values) {
    $sections = Doctrine::getTable('Section')->findAll();
    foreach($sections as $section) {
       // Do some debug with print_r($values) to find something like
       ...
       if(empty($values['section_'.$section->getId()]['selected']) {
          $this->unselected_sections[] = $section->getId();

       }
    }
    return parent::doBind($values);
  }

  public function doSave($con = null) {
       foreach($this->unselected_sections as $section_id) {
          // disembed form, something like
          unset($this->embeddedForms["section_".$section->getId()]);
       }
  }
}

Then, in your action.class.php

$shelfObject = ....
$this->form = new CustomShelfForm($shelfObject);
if(....) { 
   $this->form->bind...
   if($this->form->isValid()) {
      $this->form->save();
   }

}

This is all "on the air" code, so probably something doesn't work so well. Maybe you can try one of this solutions an let us know how it works for you. I hope this can helpyou.




回答2:


You're not the first one to ask such a behavior. Sadly, symfony isn't designed to handle an extra field in the relation table.

I did it once in the past but I can't find source code about it. But I remember that this is kind of hack which is hard to handle with embedRelation.

I found few topics around the web that might help you (at least for a starting point):

  • Form for many-to-many relation with extra field
  • Extra Field on Doctrine Many-to-Many Relationship Table
  • (might be too old) Intermediary Tables Question

In the first link, it seems that johandouma has a suitable solution but didn't post it. You might contact him to see if he remember the solution..



来源:https://stackoverflow.com/questions/12597786/symfony-1-4-doctrine-many-to-many-relationship-with-extra-field-in-intermediat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!