在 Catalyst 中使用独立模型 - 调用通用方法

Using of standalone model in Catalyst - calling of general methods

我正在关注从 2012 年开始在 Catalyst 中使用独立模型的消息:

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

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

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

我遇到错误:

"Can't locate object method "create_order" via package "WebApp::Model::DB"

从 StandaloneApp3 命名空间调用函数时,此工作:

&StandaloneApp3::create_order($params);

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

我访问 StandaloneApp3.pm 中的方法的代码是否有错误,或者在使用 DBIC::Schema 时我不希望调用此方法?如果我不应该调用 StandaloneApp3.pm 中的方法,那么正确的位置是存储可以在一个事务中写入更多 table 的方法?还可以从 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>

谢谢

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

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

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

所以重申一下,架构 不是 模型的一部分。该模型不继承自架构。它只是 has the schema as an attribute.

因此模式 class 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->schema->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 注释下方的,因为如果我们需要重新生成模式,我们不希望它被覆盖 class 以防有人更改数据库模式。

最后,我在 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, which is a model trait that's included with Catalyst::Model::DBIC::Schema 来应对这种情况。

您从配置文件或代码中的 __PACKAGE__->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 的底层可能会变得非常复杂,即使您经常使用它也很难记住所有内容,因此偶尔更新一下文档是个好主意。