PropelORMでSymfony1.4を使用すると、同じテーブル上の多対多の関係に少し問題があります。私の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
管理ジェネレーターで必要なものは自動的には表示されません。たとえば、2番目foreignTable
が別のテーブルに調整された場合に行われますsf_guard_user
。これはPropel1.3で修正できると読みましたが、Symfony1.4に含まれているPropelのバージョンがわかりません。
私の問題が皆さんによって解決されるのに十分な情報を提供したことを願っています。それ以外の場合は、次のように、子アイテムを持つアイテムを保持する別のテーブルを作成する必要があります。
アイテム<----Item_has_item<---- Combined_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は2回設定されていますが、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のバグだと思うので、明日PropelTRACに投稿します。