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