2012-07-05 6 views
2

DBIx :: Class를 사용하여 두 개의 링크에 걸쳐있는 many-to-many 접근 자 (또는 단지 has-many 관계)를 만들려고합니다. 테이블. 문제DBIx :: Class를 사용하는 many-to-many 접근 자

세 개의 데이터 테이블은 두 개의 링크 테이블, UserRolesRolePages사용자, 역할페이지 있습니다. 이 테이블 따라서 관련이 있습니다

  • 사용자이 가지고 많은 UserRoles
  • 역할이 많은 UserRoles
  • 역할이 많은 RolePages
  • 을 페이지 많은 RolePages

나를 위해 이러한 관계와 접근을 만든 촉매 도우미 스크립트

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" }, 
); 

내 최종 목표는 표시해야 할 페이지의 목록을 얻을 수있는 깨끗한 방법을 가지고있다 현재 사용자. 즉 : 나는 MyApp를 :: 스키마 :: 결과 :: 사용자 클래스에서이 메서드가 않았다

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

:

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

    return $self->result_source->schema->resultset('RolePage')->search(
     { 
      'username.username' => $self->username, 
     }, 
     { 
      join => [ 
       { 
        role => {user_roles => 'username'}, 
       }, 
       'page_name', 
      ], 
     } 
    ); 
} 
내가 확장하는 클래스를 추가 할 때까지 일을

의 MyApp :: 스키마 :: 결과 :: RolePage. 이 클래스는 다음과 같이 시작합니다 : 나는, 내 응용 프로그램을 통해이 기술을 사용했습니다 여러 결과 집합을 생성하고, 단지 지금에 문제로 실행 한

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

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

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

.

Caught exception in Lifeway::Controller::Root->auto "Single parameters to new() must be a HASH ref

MyApp::Schema::Result::User->pages() 방법에 의해 발생 :이 오류가 발생합니다. 그래서,이 오류를 피하기 위해, 나는 many-to-many 접근 자 (또는 단지 has-many 관계)를 만들려고한다고 생각했다. 사용자에서 페이지.

두 개의 링크 테이블에 걸쳐있는 그러한 접근 자/관계를 만들 수 있습니까? 그렇다면 어떻게? 나는 문서에서 예제를 찾을 수없고 스스로 아이디어가 부족하다. 그 실패, 왜 내 페이지() 메서드를 사용하여 그 오류가 점점 어떤 아이디어?

+0

검색 방법은 RS에 단 하나의 항목 만있는 경우 ResultSet이 아닌 단일 객체를 반환합니다 (일치하는 항목이없는 경우 undef). -> search_rs (...로 변경하면 문제가 해결됩니다. .) 항상 결과 집합을 반환하도록 강요합니까? – RickF

+0

아니요, 아쉽게도 '새 매개 변수에 대한 단일 매개 변수가 해시 참조이어야합니다.'오류가 발생합니다. 그래도 예상 할 수있는 데이터 유형을 반환하도록 'search_rs'로 유지하는 것이 좋습니다. 감사. – Waz

+0

그 오류는 DBIx 오류가 아닌 무스 오류와 같습니다. hash()가 아닌 단일 인수를 사용하여 new()를 호출하는 어딘가에 문제가 DBIx에 있는지 확 인해 야합니까? $ user 인스턴스를 만들고 $ user-> pages()를 직접 호출하여 자신이 생각하는 것을 반환하는지 확인할 수 있습니까? – RickF

답변

4

필자가 아는 한, 다 대다에서 많은 관계에 대한 기본 제공 지원은 없지만 자신을 구르는 것은 그리 어렵지 않습니다.

스키마 : 결과 :: 사용자.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 다 대다 관계 브리지와 기능상 동일합니다.

+0

매력처럼 작동합니다, 감사합니다. – Waz