原则 DQL:DQL 在 4 个实体之间加入



所以,我有这个实体结构:

  • 具有一些EmailUser(同时具有多个
  • );
  • 属于Domains 的每个Email(如果 email@example.com,那么我在数据库中有Domain"example.com")
  • 每个Domain都可能有一个链接到它的Profile

现在,给定一个User我想获得他可以访问的所有Profiles(如果有的话!也许Domain没有Profile)。

实体结构:

// User entity
use FOSUserBundleModelUser as BaseUser;
/**
* @ORMEntity
* @ORMTable(name="users")
*/
class User extends BaseUser
{
/**
* @ORMId
* @ORMColumn(type="integer")
* @ORMGeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var ArrayCollection
*
* @ORMOneToMany(targetEntity="AppBundleEntityEmail", mappedBy="forUser")
*/
protected $emails;
...
}

// Email entity
/**
* @ORMEntity(repositoryClass="AppBundleRepositoryEmailRepository")
* @ORMTable(name="emails")
*/
class Email
{
/**
* @var EmailValue
*
* @ORMId
* @ORMColumn(name="email", type="email", nullable=false, unique=true)
*/
protected $email;
/**
* @var Domain
*
* @ORMManyToOne(targetEntity="AppBundleEntityDomain", inversedBy="emails")
* @ORMJoinColumn(name="domain", referencedColumnName="second_level")
*/
protected $domain;
/**
* @var MyNamespaceBundleUserBundleEntityUser
*
* @ORMManyToOne(targetEntity="MyNamespaceBundleUserBundleEntityUser", inversedBy="emails")
* @ORMJoinColumn(name="for_user", referencedColumnName="id")
*/
protected $forUser;
...
}

// Domain entity
/**
* @ORMEntity(repositoryClass="AppBundleRepositoryDomainRepository")
* @ORMTable(name="domains")
*/
class Domain
{
/**
* @var string
*
* @ORMId
* @ORMColumn(type="string", nullable=false, unique=true)
*/
private $secondLevel;
/**
* @var UrlValue
*
* @ORMColumn(name="url", type="uri", nullable=false, unique=true)
*/
private $url;
...
/**
* Each Domain can be linked to only one Profile.
*
* @var Profile|null
*
* @ORMOneToOne(targetEntity="AppBundleEntityProfile", inversedBy="domain")
*/
private $profile;
/**
* Each Domain can have more than one Email.
*
* @var Collection
* @ORMOneToMany(targetEntity="AppBundleEntityEmail", mappedBy="domain")
*/
private $emails;
...
}

// Profile entity
/**
* @ORMTable(name="profiles")
* @ORMEntity(repositoryClass="AppBundleRepositoryProfileRepository")
* @ORMHasLifecycleCallbacks
*/
class Profile
{
/**
* @var int
*
* @ORMColumn(name="id", type="string", unique=true)
* @ORMId
* @ORMGeneratedValue(strategy="CUSTOM")
* @ORMCustomIdGenerator(class="AppBundleDoctrineIdGenerator")
*/
private $id;
/**
* Each Store can have only one Domain.
*
* @var Domain
*
* @ORMOneToOne(targetEntity="AppBundleEntityDomain", mappedBy="profile")
*/
private $domain;
...
}

现在,给定一个User我想获得他可以访问的所有Profiles(如果有的话!也许Domain没有Profile)。

我决定User是否可以访问Profile,如果他与DomainEmail

因此,如果UserEmailemail@example.com,他可以访问Domainexample.com 的Profile

我知道我需要加入这四张桌子,但我不知道我怎么能做到这样的JOIN

你可以帮我吗?

由于您使所有关系都是双向的,因此您可以通过联接表中Profile表来执行此类查询。您可以使用查询生成器并将以下方法添加到ProfileRepository中,以基于User实例执行搜索:

public function getUserProfiles(User $user)
{
return $this->createQueryBuilder('profile')
->addSelect('domain') // select the corresponding domain at the same time
->join('profile.domain', 'domain')
->join('domain.emails', 'emails')
->where('emails.forUser = :user')
->setParameter('user', $user)
->getQuery()
->getResult();
}

如果您只是有权访问用户 ID,则可以使用where('IDENTITY(emails.forUser) = :userId')而不是上面编写的where子句。

注意:如果用户有多个电子邮件链接到同一域/配置文件,则基础 SQL 查询将多次返回相同的配置文件条目,但如果使用getResultgetArrayResult,Doctrine 会将它们折叠为结果集中的单个条目。如果按照文档中的说明使用getScalarResult,则会得到重复项。


您也可以反过来执行此操作,并从User中加入emailsdomainprofile,以便能够访问User实例中的所有数据。重要的部分是使用leftJoin进行profile加入,以便仍然可以选择没有配置文件的域。在这种情况下,您需要向User类添加一个方法,以爬网用户的emails并检索相应的配置文件。

相关内容

  • 没有找到相关文章

最新更新