【问题标题】:DBIx:Class many-to-many relationship with additional attributeDBIx:类与附加属性的多对多关系
【发布时间】:2011-09-01 00:46:50
【问题描述】:

我正在使用 Catalyst 框架中的 DBIx::Class。我的本地目标是在用户和任务之间添加新的多对多关系。但我需要一个小技巧。用户可以在任务中扮演不同的角色(例如“工人”或“旁观者”)。

所以我有 users 表,其中包含以下字段:

  • 身份证
  • 姓名

我有包含这些字段的任务表:

  • 身份证
  • 标题
  • 说明

我的关系表 user_tasks 包含以下字段:

  • user_id
  • task_id
  • 角色

我已经设置了从users到user_tasks的has_many,从tasks到user_tasks的has_many以及对应的many_to_many关系用户和任务之间。那个简单的部分可以正常工作。

然后,例如,我想获取我的用户列表,包括用户在 $task_id 标识的任务中的角色:

my $users = $schema->resultset('User')->with_task_role($task_id);
while (my $u = $users->next) {
    print "User: " . $u->name . ", role: " . $u->get_column('task_role');
}

那么我应该如何编写这个 with_task_role 自定义结果集,以便在我的查询中获得这个带有用户任务角色的附加字段?

【问题讨论】:

    标签: perl many-to-many catalyst dbix-class


    【解决方案1】:

    首先,多对多不是关系。它是一个访问器(一个关系桥梁)。

    其次,DBIx::Class 具有出色的文档。看看加入/预取。 在您的 ResultSet/User.pm 文件中,您应该有类似的内容:

    sub with_task_role {
        my ($self, $task_id) = @_;
    
        return $self->search({
                'task.task_id' => $task_id,
            },
            {
                join     => { 'user_task' => 'task' },
                prefetch => { 'user_task' => 'task' },
            },
        );
    }
    

    PS:抱歉,我没有看到 Ashley 已经回答了 PS2:最后一行之前的“})”应该只是“)”(已修复)

    【讨论】:

    • 我已经知道 DBIx::Class 有一个出色的文档,因为我首先查看了那里。而且我已经尝试过上面的这段代码,但是它无法从这个查询中获取 user_tasks.role 字段!
    • 嗯。对不起。这段代码确实有效,那是我的实现,但没有(我使用了 join OR prefetch,而不是一起使用)。
    • 很高兴听到它在工作,它应该也可以在没有预取的情况下工作(仅使用连接),但是每次使用 user_tasks 或任务中的任何列时都会访问数据库。
    • 还有一件事:这个连接过滤掉了空连接,我更喜欢使用 undef 值。 IE。即使用户在任务中没有任何角色,也会列出他们。
    • 请参阅文档中的 join_type:search.cpan.org/~frew/DBIx-Class-0.08192/lib/DBIx/Class/… 如果您有任何其他问题,最好在 irc 频道 (irc.perl.org #dbix-class) 提问,您会得到那里有更多帮助
    【解决方案2】:

    这是来自 XUL(即 不再受任何浏览器支持)DBIC master class(.xul 资源)的幻灯片。我强烈建议下载幻灯片,以纯文本形式阅读,以便查看。它们让我大开眼界。

    您必须调整结果源名称以匹配您自己的名称,但 这应该是您想要的,并且可以更灵活地启动 _role_to_id 允许您传递角色对象或 ID。

      sub with_role {
        my ($self, $role) = @_;
        $self->search({
            'role_links.role_id' => $role->id
          },
          { join => 'role_links' }
        );
      }
    
      sub _role_to_id {
        my ($self, $role) = @_;
        return blessed($role) ? $role->id : $role;
      }
    
      sub with_any_role {
        my ($self, @roles) = @_;
        $self->search({
            'role_links.role_id' => {
              -in => [
                map { $self->_role_to_id($_) } @roles
              ]
            }
          },
          { join => 'role_links' }
        );
      }
    

    【讨论】:

    • 谢谢!这对我在这个方向上的进一步工作非常有帮助,但不能解决在不过滤角色的情况下将角色列添加到现有结果集中的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-01
    • 1970-01-01
    • 2022-08-18
    • 2011-01-16
    • 2012-10-27
    • 2022-10-25
    相关资源
    最近更新 更多