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

时间:2016-11-26 08:45:06

标签: perl catalyst

我在2012年的出现日历中收到使用独立模型的催化剂:

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

收到此收据后,我将从当前的胖模型转移现有代码。我希望在一般级别的Model中有一些方法 - 我希望将它们放在这个例子中lib/StandaloneApp3.pm文件中(例如,创建顺序意味着在表order_header,table order_item和table log中创建记录)并从中调用它们带代码的控制器:

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

我收到错误:

  

“无法通过包找到对象方法”create_order“   “Web应用程序::型号:: DB”

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

&StandaloneApp3::create_order($params);

我认为这不是一个好方法,因为我的Controller应该只连接到Catalyst Model而不是直接连接到独立库。

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

感谢您的解释和示例。

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

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

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

独立模型: file: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; 

配置: file:webapp.conf

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

谢谢

1 个答案:

答案 0 :(得分:1)

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

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

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

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

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

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

修补此问题的最简单方法是在create_order中创建方法WebApp::Model::DB,该方法在schema上调用具有相同名称的方法。

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

sub create_order {
    my $self = shift;

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

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

为了证明这一点,我在create_order中写了StandaloneApp3,如下所示:

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

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

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__->config(...)内加载它。我更喜欢它,因为在阅读代码时更容易看到发生了什么,你仍然可以在配置文件中覆盖它。

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

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

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

1;

这就是你需要改变的全部。如果您重新启动应用并再次请求根/,它仍然有效。

[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页面。我也做了同样的事。催化剂可能在下面变得非常复杂,即使你经常使用它也很难记住所有这些,所以偶尔刷新文档是一个好主意。