主键的学说多租户缺失值(带有2个PK)

时间:2018-09-20 03:34:16

标签: php symfony doctrine multi-tenant

我正在为教义建立多租户系统。我遇到了一个例外,说

  

ContactBundle \ Entity \ Contact上主键groupId的缺失值

我的多租户工作方式是将来自不同组织的数据按其groupId分开。这样,每个组织都可以拥有id = 1且不违反任何规则,因为它们的groupId和Id的组合使记录变得唯一。

这意味着您可以拥有

记录1: id = 1 groupId = 1

记录2: id = 1 groupId = 2

,它将是有效的。

我遇到的问题是我不确定如何在进行关联的联接时如何传入groupId,因此会引发该错误。由于当前查看的项目的group_id应该与列出的用于联系人和组织的group_id相同,我该如何将当前项目的groupId传递给联系人和组织的查询?这样,它就可以提取正确的记录,而不会抱怨缺少主键。

下面是我的项目实体。

<?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;
    }
}

由于我的当前系统需要groupId来获取正确的记录,因此我还将为大家提供find()和findAll()的替代品。

/**
 * @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;
}

谢谢那些提前的家伙!

1 个答案:

答案 0 :(得分:0)

将我的评论写下来作为答案,因为此处需要更多空间。因此,不,我建议:我建议您将复合键的第二部分(groupid)替换为与组实体的实际关联,而不是手动管理的id字段(https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/tutorials/composite-primary-keys.html#use-case-1-dynamic-attributes)。

关于您的原始问题,我实际上不确定您的问题是什么。如果您有可用的Project实体,则可以通过相关的getter直接访问连接的联系人和组织。

我不确定是否为您的用例正确定义了关联;您已将项目的关联定义为一对一,这基本上意味着,除了一个拥有一个联系人并属于一个组织的项目之外,围绕一个联系人只能拥有一个项目而一个组织可以进行另一种方式只有一个项目...即他们听起来应该将它们定义为ManyToOne关联(?)