How create an extra field in an unidirectional many-to-many relation? - symfony

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
`

Related

Doctrine ManyToMany Relation 'The table with name already exists

I have Entity Party. Shortly it looks like this:
AppBundle\Entity\Main\Party:
type: entity
table: main.party
id:
id:
type: integer
nullable: false
id: true
generator:
strategy: IDENTITY
fields:
legalName:
type: string
nullable: false
length: 255
options:
fixed: false
column: legal_name
manyToMany:
partiesForPartner:
targetEntity: AppBundle\Entity\Main\Party
mappedBy: partnersForParty
fetch: EXTRA_LAZY
cache:
usage: NONSTRICT_READ_WRITE
partnersForParty:
cascade: ["all"]
targetEntity: AppBundle\Entity\Main\Party
inversedBy: partiesForPartner
fetch: LAZY
joinTable:
name: main.party_partnership
joinColumns:
party_id:
referencedColumnName: id
inverseJoinColumns:
partner_id:
referencedColumnName: id
Also there is one more entity PartyPartnership. which includes some additional props.
AppBundle\Entity\Main\PartyPartnership:
type: entity
repositoryClass: AppBundle\Repository\Main\PartyPartnershipRepository
table: main.party_partnership
uniqueConstraints:
party_partnership_ukey:
columns:
- party_id
- partner_id
id:
id:
type: integer
nullable: false
options:
unsigned: false
id: true
generator:
strategy: IDENTITY
fields:
codePartyByPartner:
type: string
nullable: true
length: 35
options:
fixed: false
column: code_party_by_partner
codePartnerByParty:
type: string
nullable: true
length: 35
options:
fixed: false
column: code_partner_by_party
manyToOne:
party:
targetEntity: AppBundle\Entity\Main\Party
cascade: { }
fetch: LAZY
mappedBy: null
inversedBy: null
joinColumns:
party_id:
referencedColumnName: id
orphanRemoval: false
partner:
targetEntity: AppBundle\Entity\Main\Party
cascade: { }
fetch: LAZY
mappedBy: null
inversedBy: null
joinColumns:
partner_id:
referencedColumnName: id
orphanRemoval: false
lifecycleCallbacks: { }
All this mapping was imported from DB except of many-to-many association in Party. Now when i try to start doctrine commands like 'doctrine:schema:validate' or 'doctrine:schema:update'. I get an error 'The table with name 'main.party_partnership' already exists.'
Symfony ManyToMany creates a table between the two entities linked.
It means it automatically create the table main.party_partnership between party and partnership.
Party ---(ManyToMany main.party_partnership)---> Partnership
You just need to reference as oneToMany, and remove the manyToMany
Party ---(OneToMany)---> PartyPartnership
Partnership ---(OneToMany)---> PartyPartnership
What worked for me after several hours: clear cache.

How to create a Doctrine2 Self-referencing Association with no hierarchy using YAML

I have an "article" entity and I want to create an association with "related" articles without any hierarchy. Simply to be able to store the fact that one article is related to multiple others.
I went through this reference but the many-to-many self reflecting had no example using YAML.
What would be the right way to do design it?
This is my current entity:
ContentBundle\Entity\Article:
type: entity
table: articles
repositoryClass: ContentBundle\Repository\ArticleRepository
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
title:
type: string
length: 255
content:
type: text
creationDate:
type: datetime
column: creation_date
updateDate:
type: datetime
column: update_date
state:
type: string
length: 255
options:
default: 'public'
oneToOne:
cover:
targetEntity: AppBundle\Entity\Image
joinColumn:
name: image_id
referencedColumnName: id
oneToMany:
notes:
targetEntity: AppBundle\Entity\Note
mappedBy: article
histories:
targetEntity: HistoricalEntry
mappedBy: article
comments:
targetEntity: AppBundle\Entity\Comment
mappedBy: article
secrets:
targetEntity: Secret
mappedBy: article
manyToOne:
author:
targetEntity: AppBundle\Entity\User
inversedBy: articles
joinColumn:
name: user_id
referencedColumnName: id
world:
targetEntity: WorldBundle\Entity\World
inversedBy: articles
joinColumn:
name: world_id
referencedColumnName: id
category:
targetEntity: WorldBundle\Entity\Category
inversedBy: articles
joinColumn:
name: category_id
referencedColumnName: id
manyToMany:
tags:
targetEntity: AppBundle\Entity\Tag
inversedBy: articles
joinTable:
name: articles_tags
joinColumns:
article_id:
referencedColumnName: id
inverseJoinColumns:
tag_id:
referencedColumnName: id
inheritanceType: JOINED
discriminatorColumn:
name: template
type: string
length: 50
discriminatorMap:
article: Article
person: Person
location: Location
organization: Organization
species: Species
options:
charset: utf8
type: InnoDB
lifecycleCallbacks: { }

Add a new column in table using .orm.yml configuration

I have a question for you. It's possible to add a new column for a table using .orm.yml configuration?
For example I have :
Shop\DesktopBundle\Entity\Order:
type: entity
repositoryClass: Shop\DesktopBundle\Repository\OrderRepository
table: order
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
order_adresse:
type: string
length: 255
order_date:
type: datetime
is_active:
type: boolean
nullable: true
created_at:
type: datetime
oneToMany:
Cart:
targetEntity: Cart
mappedBy: carts
manyToOne:
category:
targetEntity: Customer
inversedBy: orders
joinColumn:
name: customer_id
referencedColumnName: id
manyToMany:
categories:
targetEntity: Product
joinTable:
name: order_details
joinColumns:
order_id:
referencedColumnName: id
inverseJoinColumns:
product_id:
referencedColumnName: id
lifecycleCallbacks:
prePersist: [ setCreatedAtValue ]
So I tried to add the column "quantity" in relation many to many > order_details table
You tried to add quantity to the relation not to the table. Try this:
manyToMany:
categories:
targetEntity: Product
joinTable:
name: order_details
joinColumns:
order_id:
referencedColumnName: id
inverseJoinColumns:
product_id:
referencedColumnName: id
fields: # if you already have 'fields' append to it
quantity:
type: int
A good example of setting your entity using yml is here: http://doctrine-orm.readthedocs.org/en/latest/reference/yaml-mapping.html#example

Symfony2 > Doctrine > double oneToMany combined key

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

Failed on insert entity with many related entities

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!

Resources