Question

I'm building my first application with symfony2. I want to create this database layout with entities.

# document

document_id | INT | AI | PK

document_name | STRING

services | RELATION MANY2MANY

...

# service

service_id | INT | AI | PK

service_name | STRING

...

*# _table_document_service*

document_id | INT

service_id | INT

amount | INT | DEFAULT 1

It's not a problem to create the entities document and service. To create the relation between document and service I will use the ManyToMany-Relation like this one:

 /**
 * @ORM\ManyToMany(targetEntity="Services")
 * @ORM\JoinTable(name="_table_document_service",
 *     joinColumns={@ORM\JoinColumn(name="document_id", referencedColumnName="id")},
 *     inverseJoinColumns={@ORM\JoinColumn(name="service_id", referencedColumnName="id")}
 * )
 */
 private $services;

But I want that in the join table there should also be a column called amount. How can i do that?

Was it helpful?

Solution

Considering that you want to add extra fields on a relation, then it's not a relation anymore but clearly -"designly" speaking- an association object.

Hence, what you want in your "table document service" table is something like that

Document ------- Table document service -------- Service

Doing so means 2 things :

Many to one associations between Document ---- Table document service and Table document service -------- Service

A sort of "Composite key" in the Table document service entity based on these associations (your primarykey then becomes a composite of the relations between these objects.

Here are some examples : as you can see in the official doctrine 2 documentation you can do assotiations based on manytoone with composite keys as follow.

EDIT : here is some bunch of code, trying to follow your example.

use Doctrine\ORM\Mapping\Entity, Doctrine\ORM\Mapping\Id, Doctrine\ORM\Mapping\Column, Doctrine\ORM\Mapping\ManyToOne, Doctrine\ORM\Mapping\OneToMany;

/** @Entity */
class Document
{
    /** @Id @Column(type="integer") @GeneratedValue */
    protected $id;

    /** @OneToMany(targetEntity="OrderItem", mappedBy="document") */
    protected $tableDocumentService;

    /** your attributes here, it isn't important here **/

    public function __construct(Customer $customer)
    {
        $this->tableDocumentService = new ArrayCollection();
        // some logic here if you need it
    }   
}

/** @Entity */
class Service
{
    /** @Id @Column(type="integer") @GeneratedValue */
    protected $id;

    /** @Column(type="string) *§
    protected $name;
}

/** @Entity */
class TableDocumentService
{
    /** @Id @ManyToOne(targetEntity="Document") */
    protected $document;

    /** @Id @ManyToOne(targetEntity="Service") */
    protected $service;

    /** @Column(type="integer") */
    protected $amount = 1;

}

I can add that, I guess, you can add too another OneToMany association in the Service class as the doc did for the Document entity, something like

/** @OneToMany(targetEntity="OrderItem", mappedBy="service") */
protected $tableDocumentService;

OTHER TIPS

the answer of @YoannCh is correct but the correct annotation is

for Document Entity:

    /**
 * @ORM\Entity
 * @ORM\Table(name="Document")
 */
class Document
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue
     */
    private $id;

    /**
     * @ORM\Column(type="string")
     */
    private $name;

    /**
     * @ORM\OneToMany(
     *  targetEntity="DocumentService", mappedBy="documentId")
     */
    private $documentService;
    //...

Service Entity is :

/**
 * @ORM\Entity
 * @ORM\Table(name="service")
 */
class Service
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue
     */
    private $id;

    /**
     * @ORM\Column(type="string")
     */
    private $name;

    /**
     * @ORM\OneToMany(
     *  targetEntity="DocumentService", mappedBy="serviceId", 
     *  )
     */
    private $documentService;
    // ...

DocumentService Entity (Join table between document and service) is :

/**
 * @ORM\Entity
 * @ORM\Table(name="document_service")
 */
class DocumentService
{ 
    /**
     * @ORM\ManyToOne(targetEntity="Document", inversedBy="documentService")
     * @ORM\JoinColumn(name="document_id", referencedColumnName="id")
     */
    private $documentId;

    /**
     * @ORM\ManyToOne(targetEntity="Service", inversedBy="documentService")
     * @ORM\JoinColumn(name="company_id", referencedColumnName="id")
     */
    private $serviceId;

    /**
     * @ORM\Column(type="integer", name="amonut")
     */
    private $amonut;  

this article discuss the same problem you had asked with example

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top