Symfony 1.4 doctrine - 与中间表中的额外字段的多对多关系

时间:2012-09-26 08:41:46

标签: doctrine many-to-many symfony-1.4 field

有3个表:shelf,section和shelf_has_section中间表,以支持n-m关系。来自symfony doctrine:build-schema的模式构建如下所示。

简单地说,

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

架构。

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

我设法通过在架构中向Shelf添加以下关系来将Sections显示为复选框列表。我还需要在部分前面显示一个文本字段复选框,以便输入书籍数量。

Sections:
  class: Section
  refClass: ShelfHasSection
  local: shelf_id

只需检查可用部分的复选框列表,然后添加已选中部分的图书数量。

我试图通过embedRelation()等来实现,但缺乏我的symfony知识并没有让我在那里。任何帮助高度赞赏。

2 个答案:

答案 0 :(得分:2)

从理论上讲,如果一个n-m关系表有自己的字段,它就会成为一个实体本身,所以n-m关系的学说模型与这个问题不匹配......但是: - 首先,您必须重新定义模式以将foreignAliases添加到n-m实体:

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**

如果您正在尝试使其在生成的模块上运行,则您的复选框提示无法解决。我建议你使用ahDoctrineEasyEmbeddedRelationsPlugin,并将关系ShelfHasSections嵌入到你的架子表格中。插件嵌入的ShelfHasSectionForm可能具有该部分的自动完成字段,以及书籍数量的输入。因此,当您想要将某个架子与一个部分相关联时,请添加一个表单(使用该插件)并选择值。 关于如何避免重复部分的最新问题....我想你应该应用一些javascript过滤器来记住女巫部分已经相关并使用自动完成查询发送它,所以教条查询可以排除这些部分....声音非常讨厌,而且它是,但它是我能想出的唯一一个解决方案。

如果您没有使用生成器,而是使用某些自定义操作/模板,我想问题会变得更容易: 将1个CustomShelfHasSectionForm嵌入到您的货架表格中(每个部分一个)。然后,为每个表单添加一个复选框小部件(可能带有sfWidgetFormInputCheckbox)以选择关系。他们,处理表单删除没有选中复选框的嵌入表单。 Somethig喜欢:

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()]);
       }
  }
}

然后,在你的action.class.php

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

}

这是所有“无线”代码,所以可能某些东西不能很好地工作。也许您可以尝试其中一种解决方案,让我们知道它是如何为您服务的。我希望这可以帮助你。

答案 1 :(得分:0)

你不是第一个提出这种行为的人。遗憾的是,symfony不是为处理关系表中的额外字段而设计的。

我过去曾做过一次,但我找不到有关它的源代码。但我记得这是一种很难用embedRelation处理的黑客。

我发现网上的一些主题可能对您有所帮助(至少在起点上):

在第一个链接中,似乎 johandouma 有一个合适的解决方案,但没有发布。您可以联系him,看看他是否记得解决方案..