学说:渴望加载懒惰关系的关系?

Wim*_*mer 6 php orm doctrine lazy-loading doctrine-orm

我正在使用Doctrine 2来绘制学术日程.以下是关系的简化介绍:

  • 一个班级活动(一对多)
    • 一个事件有一个类型(多对一)
    • 一个事件有一个位置(多对一)

使用$em->find()我只能使用延迟加载的关系来获取.或者使用带有连接的DQL,我可以急切地加载整个对象图.是否存在介于两者之间的解决方案?

我想获取一个具有延迟加载关系的,然后在某些条件下触发事件关系和所有事件属性的急切加载.因此,当我调用类似的东西时$class->getEventsHydrateAll(),所有事件事件类型以及事件位置将立即被水合.

我想我可以通过更新我的事件模式来标记类型位置关系来实现这一点fetch="EAGER".但我想控制这种深度水合作用何时发生.

这是我在类库中进行的一次尝试,但是Doctrine正在运行单独的查询来查找每种类型位置.

$query = $this->_em->createQuery('
        SELECT c FROM My\Entity\Class c
        WHERE c.id = :classId
');
$query->setParameter('classId', $classId)
      ->setFetchMode('My\Entity\Event', 'type', 'EAGER')
      ->setFetchMode('My\Entity\Event', 'location', 'EAGER');

try {
    return $query->getSingleResult();
} catch (\Doctrine\ORM\NoResultException $e) {
    return NULL;
}
Run Code Online (Sandbox Code Playgroud)

有谁知道Doctrine是否支持这个?谢谢!

Dan*_*elM 5

特尔;博士:

您可以在类属性上使用 EAGER 标志,让它急切地加载它的关系。http://doctrine-orm.readthedocs.org/en/latest/reference/annotations-reference.html#manytoone

我不确定这是否会帮助你,但这就是我解决它的方法。

首先介绍一下我的情况。我目前正在创建一个 OAuth 2 实现,我希望对范围进行细粒度控制。范围非常细化(例如电子邮件、用户名等),然后您可以为每个范围设置单独的权限以进行读取、创建、编辑和删除。

这是一个数据库图,大致显示了这种关系:

在此处输入图片说明

所以我的问题是,例如,我如何查看是否允许特定令牌读取(权限)用户名(范围)?

如果我加载令牌,然后获得它的所有权限,然后 foreach读取权限,我检查用户名范围,然后这是大量的数据库访问。

测试代码:

$permissions = $this->getOAuthHelper()
                    ->getAccessToken($accessToken)
                    ->getPermissions();
$results = [];
foreach ($permissions as $permission) {
    $results[] = $permission->getScope()->getTitle();
}
return $results;
Run Code Online (Sandbox Code Playgroud)

查询日志:

150630 10:49:47    54 Connect   root@localhost on api
150630 10:49:51    54 Query     SELECT t0.id AS id1, t0.token AS token2, t0.token_expiration AS token_expiration3, t0.refresh AS refresh4, t0.created_at AS created_at5, t0.deleted_at AS deleted_at6, t0.user_id AS user_id7, t0.client_id AS client_id8 FROM oauth_access_tokens t0 WHERE t0.token = 'user-test-token' LIMIT 1
                   54 Query     SELECT t0.id AS id1, t0.access_permission AS access_permission2, t0.scope_id AS scope_id3 FROM oauth_permissions t0 INNER JOIN oauth_access_to_permissions ON t0.id = oauth_access_to_permissions.permission_id WHERE oauth_access_to_permissions.access_id = '1'
150630 10:49:52    54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '1'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '2'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '3'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '4'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '5'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '6'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '7'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '8'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '9'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '10'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '11'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '12'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '13'
                   54 Quit
Run Code Online (Sandbox Code Playgroud)

但是,我们可以在这里看到,其中大部分是收集附加到权限的范围。我们可以在从权限到作用域的关系上使用eager标志来获取具有权限的作用域:

/**
 * @var Scope
 *
 * @ORM\ManyToOne(targetEntity="OAuthScope", fetch="EAGER")
 * @ORM\JoinColumns({
 *   @ORM\JoinColumn(name="scope_id", referencedColumnName="id")
 * })
 */
protected $scope;
Run Code Online (Sandbox Code Playgroud)

请注意fetch="EAGER"ManyToOne 注释上的标志。

现在,如果我们运行完全相同的代码:

150630 11:00:06    55 Connect   root@localhost on api
150630 11:00:10    55 Query     SELECT t0.id AS id1, t0.token AS token2, t0.token_expiration AS token_expiration3, t0.refresh AS refresh4, t0.created_at AS created_at5, t0.deleted_at AS deleted_at6, t0.user_id AS user_id7, t0.client_id AS client_id8 FROM oauth_access_tokens t0 WHERE t0.token = 'user-test-token' LIMIT 1
150630 11:00:11    55 Query     SELECT t0.id AS id1, t0.access_permission AS access_permission2, t0.scope_id AS scope_id3, t4.id AS id5, t4.title AS title6, t4.brief AS brief7, t4.category_id AS category_id8 FROM oauth_permissions t0 LEFT JOIN oauth_scopes t4 ON t0.scope_id = t4.id INNER JOIN oauth_access_to_permissions ON t0.id = oauth_access_to_permissions.permission_id WHERE oauth_access_to_permissions.access_id = '1'
                   55 Quit
Run Code Online (Sandbox Code Playgroud)


Geo*_*und -1

我不确定,但我认为 getSingleResult 会覆盖水合模式。

尝试“执行”,如下例所示:http://docs.doctrine-project.org/en/latest/reference/dql-doctrine-query-language.html#dql-temporarily-change-fetch-mode