【问题标题】:Many to many relation on same table同一张桌子上的多对多关系
【发布时间】:2012-06-06 09:09:44
【问题描述】:

我在使用 Symfony 1.4 和 Propel ORM 的同一张表上遇到了多对多关系的小问题。我的 schema.yml 看起来像这样:

propel:
  item:
    _attributes: { phpName: Item }
    id: { phpName: Id, type: INTEGER, size: '10', primaryKey: true, autoIncrement: true, required: true }
    type_id: { phpName: TypeId, type: INTEGER, size: '11', required: true, foreignTable: type, foreignReference: id, onDelete: RESTRICT, onUpdate: RESTRICT }
    owner_id: { phpName: OwnerId, type: INTEGER, size: '11', required: true, foreignTable: owner, foreignReference: id, onDelete: RESTRICT, onUpdate: RESTRICT }
    place_id: { phpName: PlaceId, type: INTEGER, size: '11', required: true, foreignTable: place, foreignReference: id, onDelete: RESTRICT, onUpdate: RESTRICT }
    picture_id: { phpName: PictureId, type: INTEGER, size: '11', required: false, foreignTable: picture, foreignReference: id, onDelete: RESTRICT, onUpdate: RESTRICT }
    supplier_id: { phpName: SupplierId, type: INTEGER, size: '11', required: false, foreignTable: supplier, foreignReference: id, onDelete: RESTRICT, onUpdate: RESTRICT }
    name: { phpName: Name, type: VARCHAR, size: '255', required: true }
    amount: { phpName: Amount, type: INTEGER, size: '11', required: true }
    wished_amount: { phpName: WishedAmount, type: INTEGER, size: '11', required: true }
    costs: { phpName: Costs, type: DECIMAL, size: '7', scale: '2', required: true }
    description: { phpName: Description, type: LONGVARCHAR, required: false }
    use_until: { phpName: UseUntil, type: DATE, required: false }
    last_used: { phpName: LastUsed, type: TIMESTAMP, required: false }
    last_updated: { phpName: LastUpdated, type: TIMESTAMP, required: false }
    _indexes: { item_FI_1: [type_id], item_FI_2: [owner_id], item_FI_3: [place_id], item_FI_4: [picture_id], item_FI_5: [supplier_id] }

 item_has_item:
    item_id: { type: INTEGER, required: true, foreignTable: item, foreignAlias: item, foreignReference: id, primaryKey: true}
    parent_item_id: { type: INTEGER, required: true, foreignTable: item, foreignAlias: parent_item, foreignReference: id, primaryKey: true}
    _indexes: { item_has_item_FKIndex1: [item_id], item_has_item_FKIndex2: [parent_item_id] }

但是,管理员生成器中所需的admin_double_list 不会自动出现。当第二个foreignTable 调整到另一个表时,例如sf_guard_user,它确实如此。我读过这可以在 Propel 1.3 中修复,但我不知道 Symfony 1.4 包含哪个 Propel 版本。

我希望我提供了足够的信息,以便你们解决我的问题。否则,我将不得不制作另一个包含具有子项目的项目的表,如下所示:

Item

在 j0k 的反应后编辑

在 j0k 做出反应后,我确实更新了 sfPropelORMPlugin,它确实识别了这种关系。但是,我在保存时仍然出错(仅在建立关系时):

Unable to execute INSERT statement [INSERT INTO `item_has_item` (`ITEM_ID`) VALUES (:p0)]
[wrapped: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a 
child row: a foreign key constraint fails (`SI/item_has_item`, CONSTRAINT 
`item_has_item_FK_1` FOREIGN KEY (`parent_item_id`) REFERENCES `item` (`id`))]

经过长时间的广泛搜索,我发现表单生成器无法正确理解同一张表上的多对多关系。在函数 saveItemHasItemList($con = null):

$c = new Criteria();
$c->add(ItemHasItemPeer::ITEM_ID, $this->object->getPrimaryKey());
ItemHasItemPeer::doDelete($c, $con);

$values = $this->getValue('item_has_item_list');
if (is_array($values))
    {
      foreach ($values as $value)
      {
        $obj = new ItemHasItem();
        $obj->setItemId($this->object->getPrimaryKey());
        $obj->setItemId($value);
        $obj->save();
      }
    }

如您所见,ItemId 设置了两次,而 ParentItemId 没有设置,因此是约束值。它应该生成为:

$c->add(ItemHasItemPeer::ITEM_ID, $this->object->getPrimaryKey());
$c->add(ItemHasItemPeer::PARENT_ITEM_ID, $this->object->getPrimaryKey());

&&

$obj->setParentItemId($this->object->getPrimaryKey());
$obj->setItemId($value);

这解决了保存问题,但是,它仍然没有显示已经选择的关系。要解决这个问题,您还应该更改 updateDefaultsFromObject():

foreach ($this->object->getItemHasItemsRelatedByItemId() as $obj)

应该是:

foreach ($this->object->getItemHasItemsRelatedByParentItemId() as $obj)

请记住,这些函数位于 form/base/BaseItemForm.class.php 中,但这些函数应该被覆盖在 /form/ItemForm.class.php 中。

我相信这是一个 Propel 错误,所以我明天会在 Propel TRAC 上发布它。

【问题讨论】:

  • 更好地报告Github上的错误。
  • 对应的GitHub票:Ticket

标签: symfony1 many-to-many symfony-1.4 propel


【解决方案1】:

如果你使用的是最新的 symfony 1.4,它使用Propel 1.4.2

您应该尝试使用 Propel 插件的new version。它使用 Propel 1.6。

【讨论】:

  • 谢谢,但是出现了另一个错误,如上面我的编辑中所述。
猜你喜欢
  • 1970-01-01
  • 2018-03-19
  • 1970-01-01
  • 1970-01-01
  • 2013-06-19
  • 2013-02-17
  • 2012-05-23
  • 1970-01-01
  • 2012-08-27
相关资源
最近更新 更多