简体   繁体   中英

Doctrine Multi-Tenancy Missing Value From Primary Key (With 2 PKs)

I am working on a multi-tenancy system for Doctrine. I ran into an exception that said

Missing value for primary key groupId on ContactBundle\\Entity\\Contact

The way my multi-tenancy works is by having the data from different organizatiosn seperated by their groupId. That way each organization can have an id=1 and not break any rules because the combination of their groupId and the Id is what makes the record unique.

This means that you can have

record 1: id = 1 groupId = 1

record 2: id = 1 groupId = 2

and it would be valid.

The problem that I am running into is the fact that I am not sure how to pass in the groupId for when it goes to do the joins for my associations, so it throws that error. Since the group_id of the currently viewed project should be the same as the ones listed for contact and organization, how would I go about passing the current project's groupId into the query for contact and organization? That way it pulls the right record and doesn't complain about missing a primary key.

Below is my Project Entity listed.

<?php

namespace ProjectBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Project
 *
 * @ORM\Table(name="project")
 * @ORM\Entity(repositoryClass="ProjectBundle\Repository\ProjectRepository")
 */
class Project
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     */
    private $id;

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

    /**
     * @var string
     *
     * @ORM\Column(name="description", type="string", length=2500)
     */
    private $description;

    /**
     * @var int
     *
     * @ORM\OneToOne(targetEntity="ContactBundle\Entity\Contact", inversedBy="projects")
     * @ORM\JoinColumn(name="contact_id", referencedColumnName="id")
     *
     */
    private $contactId;


    /**
     * @var int
     *
     * @ORM\OneToOne(targetEntity="ContactBundle\Entity\Organization", inversedBy="projects")
     * @ORM\JoinColumn(name="organization_id", referencedColumnName="id")
     */
    private $organizationId;


    /**
     * @var int
     *
     * @ORM\Column(name="group_id", type="integer")
     * @ORM\Id
     */
    private $groupId;

    public function __construct($id, $groupId){
        $this->id = $id;
        $this->groupId = $groupId;
    }

    /**
     * Get id
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     *
     * @return Project
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set description
     *
     * @param string $description
     *
     * @return Project
     */
    public function setDescription($description)
    {
        $this->description = $description;

        return $this;
    }

    /**
     * Get description
     *
     * @return string
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * Set contactId
     *
     * @param integer $contactId
     *
     * @return Project
     */
    public function setContactId($contactId)
    {
        $this->contactId = $contactId;

        return $this;
    }

    /**
     * Get contactId
     *
     * @return int
     */
    public function getContactId()
    {
        return $this->contactId;
    }

    /**
     * Set organizationId
     *
     * @param integer $organizationId
     *
     * @return Project
     */
    public function setOrganizationId($organizationId)
    {
        $this->organizationId = $organizationId;

        return $this;
    }

    /**
     * Get organizationId
     *
     * @return int
     */
    public function getOrganizationId()
    {
        return $this->organizationId;
    }
}

I will also give you guys my substitutes for find() & findAll() since my current system requires the groupId to get the right record.

/**
 * @param integer $groupId
 * @param integer $id
 */
public function findDataCollection(int $groupId)
{
    $qb = $this->repository->createQueryBuilder('e');
        $qb
            ->andWhere('e.groupId = :groupId')
            ->setParameter('groupId',$groupId);
        return $qb->getQuery()->getResult();
}

/**
 * @param integer $groupId
 * @param integer $id
 */

public function findData(int $groupId, $id)
{
    if(empty($id)){
        return false;
    }
    $qb = $this->repository->createQueryBuilder('e');
    $qb
        ->andWhere('e.id = :id')
        ->andWhere('e.groupId = :groupId')
        ->setParameter('id', $id)
        ->setParameter('groupId',$groupId);
    $data =  $qb->getQuery()->getOneorNullResult();
    return $data;
}

Thank's lots ahead of time guys!

writing my comments down as an answer as they require somewhat more space here. So nope, I was recommending that: I was recommending that you would replace the second part of your composite key (groupid) to be an actual association to the group entity instead of being a manually managed id field ( https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/tutorials/composite-primary-keys.html#use-case-1-dynamic-attributes ).

As for your original question, I'm not actually sure what your issue is. If you would have the Project entity available, you can directly access the connected contact and organization via the related getters.

I'm not sure whether your associations are correctly defined for your use case or not; you have defined the associations as one-to-one for your Project, which basically means that in addition to one project having one contact and belonging to one organization, also the other way around that one contact can have only one project and one organization can only have only one project... Ie they sound like they should be defined as ManyToOne associations (?)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM