DBIx:带有附加属性的类多对多关系

发布于 2024-11-09 07:08:11 字数 964 浏览 2 评论 0原文

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

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

  • id
  • name

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

  • id
  • title
  • description

我有关系表 user_tasks 与这些字段:

  • user_id
  • task_id
  • 角色

我已设置 has_many 从 usersuser_tasks,has_many 从 tasksuser_tasks 以及用户任务之间对应的多对多关系。这个简单的部分按其应有的方式工作。

然后,例如,我想获取我的用户列表,包括 $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 自定义结果集,以在查询中获取带有用户任务角色的附加字段?

I'm working with DBIx::Class in Catalyst framework. My local goal is to add a new many-to-many relationship between users and, let's say, tasks. But there's one little trick I need. User can have different roles in task (like 'worker' or 'spectator').

So I have users table with these fields:

  • id
  • name

I have task table with these fields:

  • id
  • title
  • description

And I have relationship table user_tasks with these fields:

  • user_id
  • task_id
  • role

I have set up has_many from users to user_tasks, has_many from tasks to user_tasks and corresponding many_to_many relationships between users and tasks. And that plain part works as it should.

Then, for example, I want to get my user list including user's role in task identified by $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');
}

So how should I code this with_task_role custom resultset to get this additional field with user's task role in my query?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

对风讲故事 2024-11-16 07:08:11

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

其次,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:最后一行“})”之前应该只有“)”(已修复)

First of all many-to-many is not a relationship. It's a accessor (a relationship bridge).

Second, the DBIx::Class has an excellent documentation. Take a look at join/prefetch.
In your ResultSet/User.pm file you should have something like:

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: Sorry, I didn't see that Ashley already answered
PS2: Before the last line "})" should be ")" only (fixed it)

清秋悲枫 2024-11-16 07:08:11

这是来自 XUL 的一些 User 结果集代码,未更改(即
任何浏览器均不再支持) 的幻灯片数据库IC
大师班
(.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' }
    );
  }

This is some User resultset code, unchanged, from the XUL (which is
no longer supported by any browsers) slideshow of the DBIC
master class
(.xul resource). I highly recommend downloading the slides, which read fine as plain text, to review. They were a great eye-opener for resultsets for me.

You'll have to adjust the result source names to match your own but
this should be what you want and a bit more flexible to boot with the
_role_to_id which allows you to pass role objects or ids.

  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' }
    );
  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文