迁移Catalyst应用时FormFu DBIC使用点符号调用ResultSet方法报错
resultset: MyTable.my_sub在新服务器报错的问题 问题原因
旧服务器上的HTML::FormFu::Model::DBIC版本包含隐式解析resultset配置中点符号的逻辑——它会自动将MyTable.my_sub拆分为基础结果集名称MyTable和后续要调用的方法my_sub,执行$schema->resultset('MyTable')->my_sub。而新服务器上的模块版本移除了这个非标准功能,直接将完整的MyTable.my_sub当作结果集源名称传入$schema->resultset(),但你的Schema中不存在名为MyTable.my_sub的数据源,因此抛出Can't find source错误。
你观察到的$schema类型差异(包装类vs直接的myapp::Schema)不影响核心问题,只是FormFu获取Schema的方式和控制器不同,本质还是版本导致的功能缺失。
解决方案
1. 对齐新旧服务器的模块版本
检查旧服务器上HTML::FormFu::Model::DBIC的版本:
cpan -D HTML::FormFu::Model::DBIC
在新服务器安装完全相同的版本:
cpanm HTML::FormFu::Model::DBIC@x.y.z
(将x.y.z替换为旧服务器的版本号)
2. 使用标准FormFu配置替代点符号
不依赖非标准的点符号解析,改用FormFu支持的标准方式获取筛选后的结果集:
方法A:用options_from_sub自定义数据源
在FormFu的YAML配置中替换resultset配置:
elements: - type: Select name: my_field options_from_sub: "MyApp::Controller::YourController::get_filtered_rs"
然后在对应控制器中实现这个子例程:
sub get_filtered_rs { my ($self, $form) = @_; # 从Form的stash或Catalyst上下文获取Schema my $schema = $form->stash->{schema} || $self->schema; # 返回筛选后的结果集条目 return $schema->resultset('MyTable')->my_sub->all; }
方法B:在Schema中注册命名结果集
在你的myapp::Schema类中添加一个自定义方法,返回经过my_sub筛选的结果集:
sub resultset_my_table_filtered { my $self = shift; return $self->resultset('MyTable')->my_sub; }
然后在FormFu配置中直接使用这个命名结果集:
resultset: my_table_filtered
方法C:修改HTML::FormFu::Model::DBIC代码(不推荐)
如果必须保留原配置格式,可以临时修改模块代码,手动添加点符号解析逻辑:
找到HTML/FormFu/Model/DBIC.pm中获取结果集的代码段,替换为:
# 原代码可能类似:my $rs = $schema->resultset($rs_name); my ($source_name, $method) = split /\./, $rs_name, 2; my $rs = $schema->resultset($source_name); $rs = $rs->$method if $method;
注意:修改核心模块会导致后续升级困难,仅作为临时应急方案。
内容的提问来源于stack exchange,提问作者Mike Bennett

