Используя DBIx :: Class, я пытаюсь создать метод доступа «многие ко многим» (или даже просто отношение «много ко многим»), охватывающий две таблицы ссылок.
Речь идет о трех таблицах данных: Пользователи, Роли и Страницы, с двумя таблицами ссылок UserRoles и 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 ref.
что вызвано моим MyApp::Schema::Result::User->pages()
методом. Итак, чтобы избежать этой ошибки, я решил попробовать создать метод доступа «многие ко многим» (или даже просто отношение «много ко многим») из Пользователи в Страницы. .
Можно ли создать такой аксессуар / отношение, которое охватывает две таблицы ссылок? Если да, то как? Я не могу найти пример в документации, и у меня самого кончились идеи. В противном случае, есть идеи о том, почему я получаю эту ошибку с помощью метода страниц ()?
Single parameters to new() must be a HASH ref
. Возможно, лучше оставить его какsearch_rs
, чтобы гарантировать, что он возвращает предсказуемый тип данных. Спасибо. - person Waz   schedule 06.07.2012/opt/ActivePerl-5.14/site/lib/Moose/Object.pm
. - person Waz   schedule 07.07.2012die Dumper $c->user->pages;
в начале моего корневого контроллера. Казалось, что он вернул что-то разумное как для вашего новогоpages()
метода (как указано ниже), так и для моего старого. Однако мой старый метод вызывает ошибку при использовании в этом операторе:$c->user->pages->search(undef, {columns => ['page_name'], distinct => 1, order_by => 'sort_order'})->get_column('page_name')->all
- person Waz   schedule 07.07.2012->pages->search(undef,...)
, похоже, работает нормально, если у меня есть хорошийpages()
метод. - person Waz   schedule 12.07.2012