加入尝试抛出异常

Join attempt throwing exceptions

我确定我忽略了一些显而易见的事情,对于新手问题我深表歉意,但我已经花了几个小时来回浏览 DBIx::Class 和 Catalyst 的文档,但没有找到答案我需要...

我想做的是根据我的数据库的内容自动创建子菜单。我在数据库中有三个表可以这样做:地图(在其中找到子菜单项)、菜单(包含顶级菜单的名称)、maps_menus(将地图分配给顶级菜单)。我已经为 return 结果集的散列编写了一个子例程,计划使用 Template Toolkit 嵌套循环来构建顶级菜单和子菜单。

基本上,对于菜单中的每个顶级菜单,我尝试 运行 以下查询并(最终)根据结果构建子菜单:

select * FROM maps JOIN maps_menus ON maps.id_maps = maps_menus.id_maps WHERE maps_menus.id_menus = (current id_menus);

这里是子程序,位于lib/MyApp/Schema/ResultSet/Menus.pm

# Build a hash of hashes for menu generation
sub build_menu {
    my ($self, $maps, $maps_menus) = @_;

    my %menus;

    while (my $row = $self->next) {
        my $id = $row->get_column('id_menus');
        my $name = $row->get_column('name');
        my $sub = $maps_menus->search(
            { 'id_maps' => $id },
            { join => 'maps',
                '+select' => ['maps.id_maps'],
                '+as' => ['id_maps'],
                '+select' => ['maps.name'],
                '+as' => ['name'],
                '+select' => ['maps.map_file'],
                '+as' => ['map_file']
            }
        );   

        $menus{$name} = $sub;   

        # See if it worked...
        print STDERR "$name\n";
        while (my $m = $sub->next) {
            my $m_id = $m->get_column('id_maps');
            my $m_name = $m->get_column('name');
            my $m_file = $m->get_column('map_file');

            print STDERR "\t$m_id, $m_name, $m_file\n";
        }
    }
    return \%menus;
}

我是从 lib/MyApp/Controller/Maps.pm 打电话来的,所以...

$c->stash(menus => [$c->model('DB::Menus')->build_menu($c->model('DB::Map'), $c->model('DB::MapsMenus'))]);

当我试图打开页面时,我遇到了各种异常,其中最重要的是:

[error] No such relationship maps on MapsMenus at /home/catalyst/perl5/lib/perl5/DBIx/Class/Schema.pm line 1078

据我所知,这源于对 $sub->next 的调用。我认为这意味着我的查询不正确,没有得到我认为应该得到的结果。但是,我不确定我错过了什么。

我在 lib/MyApp/Schema/Result/MapsMenus.pm

中找到了以下行,定义了与地图的关系
__PACKAGE__->belongs_to(
  "id_map",
  "MyApp::Schema::Result::Map",
  { id_maps => "id_maps" },
  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
);

...并在 lib/MyApp/Schema/Result/Map.pm

__PACKAGE__->has_many(
  "maps_menuses",
  "MyApp::Schema::Result::MapsMenus",
  { "foreign.id_maps" => "self.id_maps" },
  { cascade_copy => 0, cascade_delete => 0 },
);

不知道为什么叫它 "maps_menuses" -- 这是由 Catalyst 生成的。这可能是问题所在吗?

如有任何帮助,我们将不胜感激!

我建议使用构成多对多关系助手的两个关系的预取,如果您不需要访问行对象,也可以使用 HashRefInflator。

请注意,Catalyst 不会生成 DBIC(顺便说一句,这是 DBIx::Class 的官方缩写,DBIx 是整个命名空间)架构,SQL::Translator 或 DBIx::Class::Schema ::装载机做。查看您用来了解如何影响其命名的模块的文档。 如果他们不适合你,也可以随意更改名称。