DBIx :: Classを使用して、2つのリンクテーブルにまたがる多対多のアクセサー(または単に多対多の関係)を作成しようとしています。
問題の3つのデータテーブルはUsers、Roles、Pagesで、2つのリンクテーブルはUserRolesとRolePagesです。これらのテーブルは次のように関連しています。
- ユーザーには多くのユーザーロールがあります
- ロールには多くの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()メソッドでエラーが発生する理由について何か考えはありますか?