I've got a little problem with many to many relations on the same table using Symfony 1.4 with the Propel ORM. My schema.yml looks like this:
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] }
However, the needed admin_double_list in the admin generator does not appear automatically. It does, when the second foreignTable is adjusted to another table, for example sf_guard_user. I've read that this could be fixed in Propel 1.3, but I don't know which Propel version is included with Symfony 1.4.
I hope I gave enough information for my problem to be solved by you guys. Otherwise I will have to make another table which holds the items that have child item, like this:
Item <---- Item_has_item <---- Combined_item
EDIT AFTER REACTION FROM j0k
After the reaction from j0k, I did update the sfPropelORMPlugin, and it did recognise the relation. However, I still got an error while saving (only when a relation is made):
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`))]
I have found, after a long extensive search, that the form generator fails to correctly understand the many-to-many relation on the same table. In the function 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();
}
}
As you can see, the ItemId is twice set, while the ParentItemId is not set, hence the constraint value. It should be generated as:
$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);
This solves the saving problem, however, it still does not show the already selected relations. To solve that, you should also change the updateDefaultsFromObject():
foreach ($this->object->getItemHasItemsRelatedByItemId() as $obj)
Should be:
foreach ($this->object->getItemHasItemsRelatedByParentItemId() as $obj)
Remember, these functions are located in form/base/BaseItemForm.class.php, but the functions should be overwritten in /form/ItemForm.class.php.
I believe this is an Propel bug, so I will post it tomorrow on the Propel TRAC.
If you are using the last symfony 1.4, it uses Propel 1.4.2.
You should try to use a new version of the Propel Plugin. It uses Propel 1.6.
I'm looking to create fixtures file for the following schema (Movies library):
VodProgram:
actAs: { Timestampable: ~ }
columns:
title: { type: string(255), notnull: true }
year: { type: smallint }
...
relations:
VodPersons:
class: VodPerson
refClass: VodCasting
local: program_id
foreign: person_id
foreignAlias: VodPrograms
VodPerson:
columns:
name: { type: string(255), notnull: true }
VodCasting:
columns:
program_id: { type: integer, primary: true }
person_id: { type: integer, primary: true }
role: { type: string(255) }
rank: { type: smallint }
relations:
VodProgram: { onDelete: CASCADE, local: program_id, foreign: id }
VodPerson: { onDelete: CASCADE, local: person_id, foreign: id }
My problem is creating fixtures file with the "role" and "rank" fields present in the VodCasting table.
Here is my actual fixtures:
VodPerson:
kosinski:
name: Joseph Kosinski
VodProgram:
tron:
VodPersons: [kosinski] # where to put the role and rank infos ?
title: Tron
year: 2010
I tried something like :
VodProgram:
tron:
VodPersons:
kosinski:
rank: 1
title: Tron
...
with no luck.
Any suggestions?
Thanks.
Have you tried something like that :
VodPerson:
kosinski:
name: Joseph Kosinski
VodProgram:
tron:
title: Tron
year: 2010
VodCasting:
tron_kosinski:
role: 'Director'
rank: 1
VodPerson: kosinski
VodProgram: tron
I've got the following schema.yml file, but it's just not working correctly. Can anyone point me in the right direction please?
ClientPaymentService:
actAs: { Timestampable: ~ }
columns:
clientId: integer
name: { type: string(100), notnull: true, unique: true }
paymentServiceId: integer
config: { type: string(4096), notnull: true }
cardFormatId: integer
relations:
Client:
local: clientId
foreign: id
type: many
foreignType: one
foreignAlias: Client
PaymentService:
local: paymentServiceId
foreign: id
type: many
foreignType: one
foreignAlias: ClientPaymentService
CardFormat:
local: cardFormatId
foreign: id
type: many
foreignType: one
foreignAlias: ClientCardFormats
CountryCode:
class: CountryCode
refClass: ClientPaymentServiceCountryCode
foreign: id # country_code_id also doesn't work
local: id
ClientPaymentServiceCountryCode:
columns:
client_payment_service_id:
type: integer
primary: true
country_code_id:
type: integer
primary: true
relations:
ClientPaymentService:
local: client_payment_service_id
foreign: id
foreignAlias: ClientPaymentServiceCountryCodes
CountryCode:
local: country_code_id
foreign: id
foreignAlias: ClientPaymentServiceCountryCodes
CountryCode:
actAs: { Timestampable: ~ }
columns:
name: { type: string(100), notnull: true, unique: true }
code: { type: string(10), notnull: true, unique: true }
relations:
ClientPaymentService:
class: ClientPaymentService
refClass: ClientPaymentServiceCountryCode
local: id
foreign: id # client_payment_service_id also doesn't work
I receive the following error when trying to save something in the admin area:
Unknown record property / related component "id" on "ClientPaymentServiceCountryCode"
Thanks
Try this association:
ClientPaymentService:
.....
CountryCode:
class: CountryCode
refClass: ClientPaymentServiceCountryCode
foreign: country_code_id # country_code_id also doesn't work
local: client_payment_service_id # you must define both directions
ClientPaymentServiceCountryCode:
columns:
client_payment_service_id:
type: integer
primary: true
country_code_id:
type: integer
primary: true
// you not have to define relations here
CountryCode:
....
ClientPaymentService:
class: ClientPaymentService
refClass: ClientPaymentServiceCountryCode
local: country_code_id
foreign: client_payment_service_id
I have just follow documentation :
http://www.doctrine-project.org/projects/orm/1.2/docs/manual/defining-models/ru#relationships:join-table-associations:many-to-many
I have article admin module and a tag module
Tags are simply a single tag per row item
What I'd like to do is to embed the list of all the tags (as checkboxes) into my article module
Could I do this with embedded forms?
EDIT:
This is my schema:
article:
id: ~
title: { type: VARCHAR, size: '255', required: true }
tags: { type: VARCHAR, size: '500' }
created_at: { type: TIMESTAMP, required: true }
updated_at: { type: TIMESTAMP, required: true }
tag:
id: ~
tag: { type: VARCHAR, size: '500', required: true }
ord_id: { type: INTEGER, required: true }
created_at: ~
updated_at: ~
item_tag:
id: ~
item_id: { type: INTEGER, required: true, foreignTable: item, foreignReference: id, onDelete: cascade }
tag_id: { type: INTEGER, required: true, foreignTable: tag, foreignReference: id, onDelete: restrict }
created_at: ~
item:
id: ~
article_id: { type: INTEGER, foreignTable: article, foreignReference: id, onDelete: cascade }
So when I need the tags to be displayed and will update the above tables
If you have defined the relationship between the article and tags correctly in your model, then the generated Forms should contain tag select widgets.
Search "sfWidgetFormChoice" in the Forms documentation for more information:
http://www.symfony-project.org/jobeet/1_4/Doctrine/en/10
Note: The examples are created using the Doctrine ORM but everything should work the same way with Propel as well.
I'm getting a weird error in symfony 1.4 with doctrine 1.2. My schemas seem to be normal. But whenever I execute the doctrine:build --all --no-confirmation --and-load task, it would output the error SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'default_edition_id' cannot be null. If I set notnull to false for the default_edition_id field, it would actually just be null. Can anyone help me out on what I may be missing?
Here is my schema file (chapter.yml):
Chapter:
actAs:
Timestampable: ~
Versionable:
versionColumn: version
className: %CLASS%Version
SoftDelete: ~
columns:
name: string
chapter_number: { type: integer, notnull: true }
series_id: { type: integer, notnull: true }
default_edition_id: { type: integer, notnull: true }
disabled:
type: enum
values: [1, 0]
default: 0
notnull: true
relations:
DefaultEdition:
local: default_edition_id
class: Edition
foreign: id
foreignAlias: DefaultChapter
foreignType: one
type: one
# onDelete: CASCADE
Series:
local: series_id
foreign: id
onDelete: CASCADE
Editions:
type: many
class: Edition
local: id
foreign: chapter_id
and my edition schema (edition.yml):
Edition:
actAs:
Timestampable: ~
Sluggable:
fields: [name]
Versionable:
versionColumn: version
className: %CLASS%Version
SoftDelete: ~
columns:
name: string
completed_reads: { type: integer, notnull: true, default: 0}
views: { type: integer, notnull: true, default: 0 }
language_id: { type: integer, notnull: true }
chapter_id: { type: integer, notnull: true }
disabled:
type: enum
values: [1, 0]
default: 0
notnull: true
relations:
Pages:
type: many
class: Page
local: id
foreign: edition_id
Language:
local: language_id
foreign: id
type: one
onDelete: CASCADE
Chapter:
local: chapter_id
foreign: id
onDelete: CASCADE
Fixtures:
Chapter:
bakuman_chapter:
Series: bakuman
chapter_number: 86
DefaultEdition: edition_1
bakuman_chapter2:
Series: bakuman
DefaultEdition: edition_2
chapter_number: 90
Edition:
edition_1:
name: edition 1
Chapter: bakuman_chapter
ScanlationGroup: [group_1, group_2, group_3]
Language: english
edition_2:
name: edition 2
Chapter: bakuman_chapter2
ScanlationGroup: [group_4]
Language: japanese
edition_2_2:
name: edition 2_2
Chapter: bakuman_chapter2
ScanlationGroup: [group_4, group_2]
Language: english
"If I set notnull to false for the default_edition_id field, it would actually just be null". In this sentence, was does "it" refer to? Notnull means that the value 'null' is acceptable for this field, not that its value will always be null, if this was what you meant.