【问题标题】:Using of standalone model in Catalyst - calling of general methods在 Catalyst 中使用独立模型 - 调用通用方法
【发布时间】:2016-11-26 08:45:06
【问题描述】:

我正在关注从 2012 年的降临日历中收到在 Catalyst 中使用独立模型的信息:

http://www.catalystframework.org/calendar/2012/15 和前几天....

在收到此收据后,我正在从当前的胖模型转移现有代码。我想在模型中有一些通用级别的方法 - 我希望在这个示例中将它们放入lib/StandaloneApp3.pm 文件中(例如,创建订单意味着在表 order_header、表 order_item 和表日志中创建记录)并从 Controller 调用它们代码:

$c->model('DB')->create_order($params);

我收到错误:

“无法通过包定位对象方法“create_order” "WebApp::Model::DB"

当从 StandaloneApp3 命名空间调用函数时,这个工作:

&StandaloneApp3::create_order($params);

我认为这不是一个好方法,因为我的控制器应该只连接到 Catalyst 模型而不是直接连接到独立库。

在访问 StandaloneApp3.pm 中的方法或使用 DBIC::Schema 时我的代码中是否存在错误,我不希望调用此方法?如果我不应该调用 StandaloneApp3.pm 中的方法,那么在一个事务中存储可以写入更多表的方法的正确位置是什么?任何示例也用于从 Catalyst 外部精确调用这些方法 - 例如。从命令行?

感谢您的解释和示例。

----------- 添加代码 -------------

催化剂型号: 文件:lib\WebApp\Model\DB.pm:

package WebApp::Model::DB;
use strict;
use base 'Catalyst::Model::DBIC::Schema';
1;

独立模型: 文件:lib/StandaloneApp3.pm

use utf8; 
package StandaloneApp3;
use Moose; 
use MooseX::MarkAsMethods autoclean => 1; 
extends 'DBIx::Class::Schema';
PACKAGE->load_namespaces;
sub create_order {
    # in development 
    return "order_created"; 
}
PACKAGE->meta->make_immutable(inline_constructor => 0); 
1; 

配置: 文件:webapp.conf

<Model::DB>
    schema_class StandaloneApp3
    <connect_info>
        dsn dbi:SQLite:__path_to(data,database_file2.db)__
    </connect_info>
</Model::DB>

谢谢

【问题讨论】:

  • 请附上型号的代码。特别是包含包定义和您正在调用的子文件的顶部。
  • 我已将代码添加到主帖
  • 看起来正确。尝试摆脱 use base 并改为使用 use Moose; extends 'Catalyst...'
  • 可能是我没弄好,我已经在Model DB中删除了use base 'Catalyst::Model::DBIC::Schema';并添加了use Moose; extends 'Catalyst';,但是还是一样的错误“Can't locate object method“test” via package“ WebApp::Model::DB"
  • 顺便说一句,不要用&amp; 打电话给潜艇。

标签: perl catalyst


【解决方案1】:

您在催化剂模型WebApp::Model::DB 中使用StandaloneApp3 作为您的模式类。这意味着它是自动为您加载的 DBIx::Class 模式。架构类似于数据库对象。

要访问架构,请在模型上使用 schema 访问器方法。

$c->model('DB')->schema;

重申一下,模式不是模型的一部分。该模型不从模式继承。它只是has the schema as an attribute

因此,模式类StandaloneApp3 中的方法create_order 不是模型WebApp::Model::DB 上的方法。这是schema 属性上的一个方法。

$c->model('DB')->schema->create_order;

解决这个问题的最简单方法是在WebApp::Model::DB 中创建一个方法create_order,该方法调用schema 上具有相同名称的方法。

package WebApp::Model::DB;
# ...

sub create_order {
    my $self = shift;

    return $self->schema->create_order(@_);
}

shift 删除了 $self,因此我可以将参数列表的其余部分 @_ 传递给 $self-&gt;schema-&gt;create_order

为了证明这是可行的,我在StandaloneApp3 中写了create_order,如下所示:

package StandaloneApp3;
# ...

# You can replace this text with custom code or comments, and it will be preserved on regeneration

sub create_order {
    # in development

    warn "creating order...";
    return "order_created"; 
}

我将warn 放入其中,以便我们稍后可以在您的控制台中的日志中找到它。请注意它是如何放置在 DBIC 的注释下方的,因为如果我们稍后需要重新生成架构类以防有人对数据库架构进行了更改,我们不希望它被覆盖。

最后,我在Root 控制器中从sub index 调用模型方法。

sub index :Path :Args(0) {
    my ( $self, $c ) = @_;

    $c->model('DB')->create_order;

    # Hello World
    $c->response->body( $c->welcome_message );
}

如果您现在在浏览器中请求/(对我来说是http://localhost:5000/),它现在可以工作,并显示在日志中。我的是在 Windows 上,所以看起来有点奇怪。

[info] *** Request 1 (0.143/s) [8012] [Sun Nov 27 16:25:59 2016] ***
[debug] Path is "/"
[debug] "GET" request for "/" from "127.0.0.1"
creating order... at lib/StandaloneApp3.pm line 23.
127.0.0.1 - - [27/Nov/2016:16:25:59 +0100] "GET / HTTP/1.1" 200 5477 "-" "Mozill
a/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0
.2840.99 Safari/537.36"
[debug] Response Code: 200; Content-Type: text/html; charset=utf-8; Content-Leng
th: unknown
[info] Request took 0.012028s (83.139/s)
.------------------------------------------------------------+-----------.
| Action                                                     | Time      |
+------------------------------------------------------------+-----------+
| /index                                                     | 0.000545s |
| /end                                                       | 0.000340s |
'------------------------------------------------------------+-----------'

但是,当然,如果您有几个想要修补的方法,那么自己编写所有这些方法会有点乏味。您可以使用 AUTOLOAD 动态创建方法,但在这种情况下这似乎是错误的,所以我不打算解释。

相反,让我们使用Catalyst::TraitFor::Model::DBIC::Schema::SchemaProxy,它是included with Catalyst::Model::DBIC::Schema 的模型特征,正是这种情况。

您可以从配置文件或代码中的__PACKAGE__-&gt;config(...) 中加载它。我更喜欢那里,因为在阅读代码时更容易看到发生了什么,并且您仍然可以稍后在配置文件中覆盖它。

这是完整的WebApp::Model::DB 文件。我删除了我们在上面示例中放置的方法create_order,并包含了特征配置。

package WebApp::Model::DB;
use strict;
use base 'Catalyst::Model::DBIC::Schema';

__PACKAGE__->config(
    traits => 'SchemaProxy',
);

1;

这就是你需要改变的全部。如果您重新启动应用程序并再次请求root /,它仍然可以工作。

[info] *** Request 1 (0.111/s) [6160] [Sun Nov 27 16:43:45 2016] ***
[debug] Path is "/"
[debug] "GET" request for "/" from "127.0.0.1"
creating order... at lib/StandaloneApp3.pm line 23.
127.0.0.1 - - [27/Nov/2016:16:43:45 +0100] "GET / HTTP/1.1" 200 5477 "-" "Mozill
a/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0
.2840.99 Safari/537.36"
[debug] Response Code: 200; Content-Type: text/html; charset=utf-8; Content-Leng
th: unknown
[info] Request took 0.011867s (84.267/s)
.------------------------------------------------------------+-----------.
| Action                                                     | Time      |
+------------------------------------------------------------+-----------+
| /index                                                     | 0.000712s |
| /end                                                       | 0.000370s |
'------------------------------------------------------------+-----------'

我建议您花几分钟时间阅读我在此答案中链接的模块的 CPAN 页面。我只是做了同样的事情。 Catalyst 在底层可能会变得非常复杂,即使您经常使用它也很难记住所有内容,因此偶尔刷新一下文档是个好主意。

【讨论】:

  • 您的分析很棒,感谢您的努力和时间。模型特征Catalyst::TraitFor::Model::DBIC::Schema::SchemaProxy 我不知道,它在这种情况下有所帮助。我也在我的代码中更正了它并按预期工作。
  • @Tony 很高兴它有帮助。我只是在空闲时间通常不使用 Catalyst,因此需要一些时间来设置它。 ;)
猜你喜欢
  • 2017-02-12
  • 1970-01-01
  • 2019-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-23
  • 1970-01-01
相关资源
最近更新 更多