I have 3 entities:
Song
Artist
Genre
One song can have multiple genres and vice versa. A song can also have multiple artists and vice versa.
That's why I'm trying to create two many-to-many relationships. However, when generating the Entity clases, the first of the two is always 'overridden' by the second one and no variable or accessors are created for that one..
Here's my yaml: (updated)
Foo\BarBundle\Entity\Song:
type: entity
table: song
id:
id:
type: integer
generator:
strategy: AUTO
fields:
title:
type: string
length: 300
mime_type:
type: string
length: 20
filesize:
type: integer
length: 20
length:
type: string
length: 20
created_at:
type: datetime
gedmo:
timestampable:
on: create
manyToOne:
user:
targetEntity: Spotaset\UserBundle\Entity\User
inversedBy: songs
manyToMany:
genres:
targetEntity: Genre
inversedBy: songs
manyToMany:
artists:
targetEntity: Artist
inversedBy: songs
Foo\BarBundle\Entity\Artist:
type: entity
table: artist
id:
id:
type: integer
generator:
strategy: AUTO
fields:
name:
type: string
length: 100
unique: true
manyToMany:
songs:
targetEntity: Song
mappedBy: artistss
Foo\BarBundle\Entity\Genre:
type: entity
table: genre
id:
id:
type: integer
generator:
strategy: AUTO
fields:
name:
type: string
length: 100
unique: true
manyToMany:
songs:
targetEntity: Song
mappedBy: genres
I don't know a lot about relational databases so I don't know wether this is a bug or that this design is just bad in general..
All help is greatly appreciated!
Finally solved this (stupid) issue. Turned out I had to define both many to many under one manyToMany heading like this:
manyToMany:
genres:
targetEntity: Genre
inversedBy: songs
artists:
targetEntity: Artist
inversedBy: songs
Related
I'm trying to setup the relation between 'Products' and 'Merchants' through a linking table 'MerchantProduct' where I can store/override additional information. So the primary key consists of a combined key. I've tried to simplify the amount of fields per Entity to enhance the readability. The three Entities already worked fine before I tried to add the relations in YML, but I would like to go 'all the way' with Doctrine.
The error I get is:
[Doctrine\ORM\ORMException]
Column name id referenced for relation from
BLAAT\Bundle\AdminBundle\Entity\Core\Product towards
BLAAT\Bundle\AdminBundle\Entity\Core\MerchantProduct does not exist.
I'm not really sure why I get this error and don't know how to solve it. I'm afraid it has to do with the combined primary key.
Linking-entity with extra override information
BLAAT\Bundle\AdminBundle\Entity\Core\MerchantProduct:
type: entity
table: MerchantProduct
repositoryClass: BLAAT\Bundle\AdminBundle\Entity\Core\MerchantProductRepository
id:
merchantId:
type: integer
column: merchant_id
productId:
type: string
length: 255
column: product_id
fields:
inStock:
type: boolean
column: in_stock
nullable: TRUE
productPrice:
type: float
column: product_price
nullable: TRUE
productDescription:
type: text
column: product_description
nullable: TRUE
oneToMany:
products:
targetEntity: Product
mappedBy: product_id
oneToMany:
outlets:
targetEntity: Merchant
mappedBy: merchant_id
lifecycleCallbacks: { }
Product-entity
BLAAT\Bundle\AdminBundle\Entity\Core\Product:
type: entity
table: Product
repositoryClass: BLAAT\Bundle\AdminBundle\Entity\Core\ProductRepository
id:
id:
type: string
length: 255
id: true
generator:
strategy: NONE
fields:
title:
type: string
length: 255
defaultDescription:
type: text
column: default_description
nullable: TRUE
defaultPrice:
type: float
column: default_price
nullable: TRUE
manyToOne:
sellers:
targetEntity: MerchantProduct
inversedBy: products
joinColumn:
name: product_id
referencedColumnName: id
lifecycleCallbacks: { }
Merchant-entity
BLAAT\Bundle\AdminBundle\Entity\Core\Merchant:
type: entity
table: null
repositoryClass: BLAAT\Bundle\AdminBundle\Entity\Core\MerchantRepository
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
title:
type: string
length: 255
address:
type: string
length: 255
manyToOne:
stock:
targetEntity: MerchantProduct
inversedBy: outlets
joinColumn:
name: merchant_id
referencedColumnName: id
lifecycleCallbacks: { }
I think the mappedBys in MerchantProduct should be sellers and stock and that the referencedColumnNames should be productId and merchantId (or possibly product_id and merchant_id -- I haven't tested it, but something that exists in MerchantProduct, in any case).
It's the latter that seems to cause the error, because there is no column id: it should be productId.
To deal with a compound primary key, I think you need to use multiple JoinColumns to define the manyToOne relation in Merchant and Product. If I'm reading the documentation correctly, you can combine multiple JoinColumns under JoinColumns.
So:
manyToOne:
stock:
targetEntity: MerchantProduct
inversedBy: outlets
joinColumns:
joinColumn:
name: merchant_id
referencedColumnName: merchantId
joinColumn:
name: product_id
referencedColumnName: productId
In a Symfony2 app, I have two entites: Club and Member.
I have to use a composite primary keys with four specific fields (edition, distance, district and id). Here is the ORM yml. The Club schema is correctly generated.
MyBundle\Entity\Club:
type: entity
oneToMany:
members:
targetEntity: Member
mappedBy: club
table: null
id:
edition:
type: string
length: 4
distance:
type: string
length: 1
district:
type: integer
id:
type: integer
fields:
name:
type: string
length: 255
location:
type: string
length: 255
lifecycleCallbacks: { }
My problem is now to link the Member entity. Here is my current ORM yml:
MyBundle\Entity\Member:
type: entity
manyToOne:
club:
targetEntity: Club
inversedBy: members
joinColumn:
name: club_id
referencedColumnName: ??? What if composite PK ???
table: null
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
lastname:
type: string
length: 255
firstname:
type: string
length: 255
...
What to set as referencedColumnName? How to set up the reference with a composite FK?
EDIT
I found that is possible to set multiple join colums with annotation #joinColumns{#joinColumn...#joinColumn...}. Something similar for yml configuration? I can't find any example.
Try something like this, I think it's the correct YML syntax:
manyToOne:
club:
targetEntity: Club
inversedBy: members
joinColumns:
- joinColumn:
name: club_id
referencedColumnName: id
- joinColumn:
name: club_edition
referencedColumnName: edition
- joinColumn:
name: club_distance
referencedColumnName: distance
- joinColumn:
name: club_district
referencedColumnName: district
(However, for your continued sanity, I'd strongly recommend trying to avoid composite keys where possible!)
I found this response: https://stackoverflow.com/a/9135093/620095, but I wouldn't like to use a new class. I'm looking for the best way (elegant and straightforward).
Here is the 'Tag' entity:
MyApp\CoreBundle\Entity\Tag:
type: entity
table: tag
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
name:
type: string
length: 255
nullable: false
The 'Post' entity:
MyApp\PostBundle\Entity\Post:
type: entity
table: post
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
title:
type: string
length: 255
nullable: false
content:
type: text
nullable: false
manyToMany:
Tags:
targetEntity: MyApp\CoreBundle\Entity\Tag
joinTable:
name: post_tag
joinColumns:
post_id:
referencedColumnName: id
inverseJoinColumns:
tag_id:
referencedColumnName: id
The 'Event' entity:
MyApp\EventBundle\Entity\Event:
type: entity
table: event
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
title:
type: string
length: 255
nullable: false
content:
type: text
nullable: false
manyToMany:
Tags:
targetEntity: MyApp\CoreBundle\Entity\Tag
joinTable:
name: event_tag
joinColumns:
event_id:
referencedColumnName: id
inverseJoinColumns:
tag_id:
referencedColumnName: id
Suppose I want a 'description' field in the 'event_tag' table. What should I do?
UPDATE: If is impossible, how would stay my three yml to add the quoted field?
Sorry, you have to create a new entity.
You have to considere this entity as an individual symfony entity
For example:
Product >- Stock -< Store
Product >- Bill -< User
...
And not as a link between two others entities.
#cbacelar "I updated the question. Can you help me?" => Event-Tag relationship could be sth like:
In Event entity, change manyToMany by oneToMany:
oneToMany:
EventTags:
targetEntity: MyApp\EventBundle\Entity\EventTag
mappedBy: Events
In Tag entity, change manyToMany by oneToMany:
oneToMany:
EventTags:
targetEntity: MyApp\EventBundle\Entity\EventTag
mappedBy: Tags
Create MyApp\CoreBundle\Entity\EventTag entity:
type: entity
table: event_tag
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
description:
type: text
nullable: false
manyToOne:
Events:
targetEntity: MyApp\EventBundle\Entity\Event
inversedBy: EventTags
joinColumn:
name: event_id
referencedColumnName: id
Tags:
targetEntity: MyApp\CoreBundle\Entity\Tag
inversedBy: EventTags
joinColumn:
name: tag_id
referencedColumnName: id
`
This is my first post because until now I had always found solution with your answers, until now...
I have three Entities (Bike, Category and Extra) that have some field translatable. I know there is a Translatable Extension in symfony but I discovered a bit late and I have my solution always working.
The thing is I have then 3 other tables (BikeI18N, CategoryI18N and ExtraI18N). These table link with their associated with a column bike_id (for example). Here you have the schema of Bike and Category and their I18N's tables:
Bike:
BEM\BikeBundle\Entity\Bike:
type: entity
table: null
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
marca:
type: string
length: 255
model:
type: string
length: 255
preu1Dia:
type: float
column: preu_1dia
[...]
manyToOne:
category:
targetEntity: BEM\CategoryBundle\Entity\Category
inversedBy: bikes
oneToMany:
translation:
targetEntity: BikeI18N
mappedBy: bike
cascade: [persist]
pedals:
targetEntity: Pedal
mappedBy: bike
talles:
targetEntity: Talla
mappedBy: bike
manyToMany:
accessoris:
targetEntity: Accessori
inversedBy: bikes
lifecycleCallbacks: { }
BikeI18N:
BEM\BikeBundle\Entity\BikeI18N:
type: entity
table: null
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
descripcio:
type: text
locale:
type: string
length: '2'
manyToOne:
bike:
targetEntity: Bike
inversedBy: translation
joinColumn:
bike_id:
referencedColumnName: id
lifecycleCallbacks: { }
Category:
BEM\CategoryBundle\Entity\Category:
type: entity
table: null
repositoryClass: BEM\CategoryBundle\Repository\CategoryRepository
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
oneToMany:
translation:
targetEntity: CategoryI18N
mappedBy: category
cascade: [persist]
bikes:
targetEntity: BEM\BikeBundle\Entity\Bike
mappedBy: category
lifecycleCallbacks: { }
and finally CategoryI18N:
BEM\CategoryBundle\Entity\CategoryI18N:
type: entity
table: null
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
categoryId:
type: integer
column: category_id
locale:
type: string
length: '2'
translation:
type: string
length: 255
manyToOne:
category:
targetEntity: Category
inversedBy: translation
joinColumn:
category_id:
referencedColumnName: id
lifecycleCallbacks: { }
In my "new" form I have a Category form with 4 embeded CategoryI18N forms. It works properly. The problem is the Bike and BikeI18N does not even if I did the same.
If I write $translation->setAccessori($this); in Bike::addTranslation(BikeI18N $translation) I get the error Entities passed to the choice field must be managed. Maybe persist them in the entity manager?.
If I don't write $translation->setAccessori($this); the form is saved but the relation is lost or, if I set the DB to not_nullable bike_id I get an error.
The most surprising thing that makes no sense to me is that I have setCategory($this) inside the addTranslation of the class Category...any ideas?
I resolved the issue.
The think was in my BikeI18N form builder.
class BikeI18NType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('descripcio')
->add('locale', 'hidden')
//->add('bike', 'hidden')
;
}
}
When I commented out the bike additions the problem was solved.
Thanks for reading!
I'm working with a Doctrine schema, but ran into trouble because one of the manyToOne-relationships won't persist in the database. I am clueless why this is the case, because to my eye, the syntax looks correct.
Can anyone identify the problem?
Below is my schema in yaml. There are no tables relating these two entities in my mysql-database after running
php app\console doctrine:schema:update --force.
Me\MyBundle\Entity\FreeTextField:
type: entity
table: null
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
name:
type: string
flagPrivate:
type: boolean
description:
type: text
nullable: TRUE
oneToMany:
entries:
targetEntity: FreeTextEntry
mappedBy: xfield
lifecycleCallbacks: { }
Me\MyBundle\Entity\FreeTextEntry:
type: entity
table: null
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
content:
type: text
manyToOne:
xfield:
targetEntity: FreeTextField
inversedBy: entries
manyToOne:
registration:
targetEntity: Registration
inversedBy: freeTextEntries
lifecycleCallbacks: { }
Propably the same problem as here. You need to put all the manyToOne -type associations under the same type declaration in Entity\FreeTextEntry, like so:
manyToOne:
xfield:
targetEntity: FreeTextField
inversedBy: entries
registration:
targetEntity: Registration
inversedBy: freeTextEntries