2

DBIx :: Classを使用して、2つのリンクテーブルにまたがる多対多のアクセサー(または単に多対多の関係)を作成しようとしています。

問題の3つのデータテーブルはUsersRolesPagesで、2つのリンクテーブルはUserRolesRolePagesです。これらのテーブルは次のように関連しています。

  • ユーザーには多くのユーザーロールがあります
  • ロールには多くのUserRolesがあります
  • ロールには多くのRolePagesがあります
  • ページには多くのRolePagesがあります

Catalystヘルパースクリプトは、私のためにこれらの関係とアクセサーを作成しました。

package MyApp::Schema::Result::User;

__PACKAGE__->has_many(
  "user_roles",
  "MyApp::Schema::Result::UserRole",
  { "foreign.username" => "self.username" },
  { cascade_copy => 0, cascade_delete => 0 },
);

__PACKAGE__->many_to_many("roles", "user_roles", "role");


package MyApp::Schema::Result::Role;

__PACKAGE__->has_many(
  "role_pages",
  "MyApp::Schema::Result::RolePage",
  { "foreign.role" => "self.role" },
  { cascade_copy => 0, cascade_delete => 0 },
);

__PACKAGE__->has_many(
  "user_roles",
  "MyApp::Schema::Result::UserRole",
  { "foreign.role" => "self.role" },
  { cascade_copy => 0, cascade_delete => 0 },
);

__PACKAGE__->many_to_many("page_names", "role_pages", "page_name")

__PACKAGE__->many_to_many("usernames", "user_roles", "username");


package MyApp::Schema::Result::Page;

__PACKAGE__->has_many(
  "role_pages",
  "MyApp::Schema::Result::RolePage",
  { "foreign.page_name" => "self.page_name" },
  { cascade_copy => 0, cascade_delete => 0 },
);

__PACKAGE__->many_to_many("roles", "role_pages", "role");


package MyApp::Schema::Result::UserRole;

__PACKAGE__->belongs_to(
  "role",
  "MyApp::Schema::Result::Role",
  { role => "role" },
  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
);

__PACKAGE__->belongs_to(
  "username",
  "MyApp::Schema::Result::User",
  { username => "username" },
  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
);


package MyApp::Schema::Result::RolePage;

__PACKAGE__->belongs_to(
  "page_name",
  "MyApp::Schema::Result::Page",
  { page_name => "page_name" },
  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
);

__PACKAGE__->belongs_to(
  "role",
  "MyApp::Schema::Result::Role",
  { role => "role" },
  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
);

私の最終目標は、現在のユーザーに表示する必要のあるページのリストを取得するためのクリーンな方法を用意することです。すなわち:

foreach my $page ($c->user->pages) {
    # do something with $page
}

MyApp :: Schema :: Result :: Userクラスにこのメソッドがありました:

sub pages {
    my ($self) = @_;

    return $self->result_source->schema->resultset('RolePage')->search(
        {
            'username.username' => $self->username,
        },
        {
            join => [
                {
                    role => {user_roles => 'username'},
                },
                'page_name',
            ],
        }
    );
}

これは、MyApp :: Schema :: Result::RolePageを拡張するクラスを追加するまで機能しました。そのクラスは次のように始まります。

package MyApp::Schema::ResultSet::RolePage;

use Moose;
use namespace::autoclean;
extends qw/MyApp::Schema::ResultSetX::DisplayTable/;

has '+name' => ( default => 'RolePage' );

私はアプリ全体でこの手法を使用してさまざまな結果セットを作成しましたが、現在は問題が発生しています。このエラーが発生します:

Lifeway :: Controller :: Root-> autoで例外が発生しました"new()への単一パラメーターはHASH参照である必要があります

MyApp::Schema::Result::User->pages()これは私の方法が原因です。したがって、このエラーを回避するために、ユーザーからページへの多対多のアクセサー(または単に多対多の関係)を作成しようと思いました。

2つのリンクテーブルにまたがるそのようなアクセサー/関係を作成することは可能ですか?もしそうなら、どのように?ドキュメントに例が見つからず、自分でアイデアが不足しています。それが失敗した場合、pages()メソッドでエラーが発生する理由について何か考えはありますか?

4

1 に答える 1

4

私の知る限り、多対多の関係をサポートする組み込みのサポートはありませんが、自分で作成するのはそれほど難しくありません。

Schema::Result::User.pm 内

sub pages {
  my $self = shift;
  return $self->search_related('user_roles')
    ->search_related('role')
    ->search_related('role_pages')
    ->search_related('page_name');
    # Alternatively, if you need to eliminate duplicates:
    # ->search_related('page_name', {}, {distinct => 1});
}

これは、標準の DBIx 多対多リレーションシップ ブリッジと同等の機能にかなり近いと思います。

于 2012-07-06T21:13:06.827 に答える