Как создать вложенную связь has_many или own_to с DBIx::Class?

В моем коде у меня есть три класса: Forum, Forum::Thread и Forum::Post

Что я хочу сделать, так это создать отношение «принадлежит_к» от класса Forum::Post к классу Forum и наоборот с помощью has_many, предпочтительно, без создания для него пользовательской функции. (По общему признанию, это больше интеллектуальное упражнение, чем техническое ограничение или реальная проблема, но если это возможно, я бы очень хотел знать.)

Закомментированные строки содержат мое намерение относительно отношений, но в их нынешнем виде они не работают. Я рылся в документации, но не нашел ничего, относящегося к этому конкретному случаю.

Любые указатели?

Класс форума:

package Schema::Result::Forum;

use Moose;
extends qw/DBIx::Class/;

__PACKAGE__->load_components (qw/Core/);
__PACKAGE__->table ('forum');

__PACKAGE__->add_columns (
    id => {
    is_auto_increment => 1,
    data_type         => 'integer',
  },
);

__PACKAGE__->set_primary_key ('id');

__PACKAGE__->has_many (threads => 'Schema::Result::Forum::Thread');
#This is the interesting line
#__PACKAGE__->has_many (posts => 'threads' => 'forums' );

1;

Класс потока:

package Schema::Result::Forum::Thread;

use Moose;
extends qw/DBIx::Class/;

__PACKAGE__->load_components (qw/Core/);
__PACKAGE__->table ('forum_thread');
__PACKAGE__->add_columns (
  id => {
    is_auto_increment => 1,
    data_type         => 'integer',
  },
  forum => {
    data_type         => 'integer',
  },
);

__PACKAGE__->set_primary_key ('id');

__PACKAGE__->belongs_to (forum => 'Schema::Result::Forum');
__PACKAGE__->has_many (posts => 'Schema::Result::Forum::Post');

1;

Почтовый класс:

package Schema::Result::Forum::Post;

use Moose;

extends qw/DBIx::Class/;

__PACKAGE__->load_components (qw/Core/);

__PACKAGE__->table ('forum_post');

__PACKAGE__->add_columns (
  id => {
    is_auto_increment => 1,
    data_type         => 'integer',
  },
  thread => {
    data_type         => 'integer',
  },
);

__PACKAGE__->set_primary_key ('id');

__PACKAGE__->belongs_to (thread => 'Schema::Result::Forum::Thread');
#This is the other interesting line
#__PACKAGE__->belongs_to (forum => 'thread' => 'forum');

1;

PS: Дополнительные столбцы для хранения фактического содержания были опущены для краткости.


person Williham Totland    schedule 01.03.2010    source источник
comment
Что вы ожидаете от этой вложенной связи? Что будет означать $post->forum или $forum->post в этих условиях? Разве вы не можете просто использовать $post->thread->forum и for my $thread ($forum->threads) { for my $post ($thread->posts) { } }, чтобы делать то, что вы хотите?   -  person Philip Potter    schedule 03.03.2010
comment
@Phillip Potter: я немного опасаюсь преподавания; то, что я в конце концов хочу добиться с помощью $forum->posts, — это один SQL-запрос, который извлекает все данные. $post-›forum на самом деле просто сокращение от $post-›thread-›forum, так что, я полагаю, это менее интересно.   -  person Williham Totland    schedule 04.03.2010
comment
Я предлагаю вам подписаться на список рассылки DBIx::Class и спросить там. Я не совсем уверен, как сделать то, что вы просите.   -  person Philip Potter    schedule 07.03.2010


Ответы (2)


Похоже, что вложенные отношения невозможны. has_many принимает один внешний класс, который имеет внешний ключ для вызывающего класса.

Хорошая новость заключается в том, что $forum->threads->posts возвращает один DBIx::Class::Resultset. Он не транслируется в SQL до тех пор, пока не потребуется, поэтому, когда вы вызываете $forum->threads->posts->all() или даже что-то вроде $forum->search_related('threads',{},{rows=>25})->posts->all(), выполняется только один запрос.

Если ваша цель состоит в том, чтобы иметь $post->forum, это всегда может быть метод: sub forum{$_[0]->thread->forum}

person zpmorgan    schedule 19.03.2010

Какую базу данных и тип движка вы используете? Если у вас нет внешних ключей (как, например, с таблицами myisam в MySQL), вам придется указать имена столбцов в ваших операторах отношений.

person Community    schedule 17.03.2010