如何在Catalyst应用程序中创建连接到DB的全局var $ schema?

时间:2013-03-21 15:09:44

标签: perl catalyst dbix-class

我创建了一个模型lib / MyApp / Model / Foo.pm。在里面:

...
sub bar {
  my $schema = MyApp::Schem->connect("dbi:SQLite:data.db");
}
...

它工作正常但我写的时候:

...
my $schema = MyApp::Schema->connect("dbi:SQLite:data.db");
sub bar {}
...

它不起作用并写下:

  

无法通过包“MyApp :: Schema”找到对象方法“connect”   (也许你忘了加载“MyApp :: Schema”?)...

我想创建全局$ schema var以在不同的方法中使用它。我怎样才能达到它?

3 个答案:

答案 0 :(得分:2)

Catalyst::Model::DBIC::Schema自动处理可能启动的每个进程的数据库连接。

如果使用帮助程序创建MyApp :: Model :: DBIC,如概要中所示,它将开箱即用。 SQLite的数据库凭证或数据库文件名通常放在由Catalyst::Plugin::ConfigLoader加载的Catalyst配置文件中。

请注意,您通常不会向Catalyst模型添加任何方法,也不会向DBIx :: Class架构添加任何方法。

要访问模型,无论其类型(DBIC,LDAP,...)如何,都必须在Catalyst中使用$c->model($modelname)。因此,如果您将模型命名为MyApp :: Model :: DBIC,那么这将是$c->model('DBIC')。 要访问DBIC结果集,您可以使用$c->model('DBIC')->resultset('Foo')$c->model('DBIC::Foo')这是一种特殊语法Catalyst::Model::DBIC::Schema支持。

答案 1 :(得分:0)

您是否忘记加载MyApp::Schema

当您在子例程中调用MyApp::Schema->connect时,某些其他Catalyst组件可能已加载MyApp::Schema模块并使connect方法可用。

在子例程之外,您的应用程序将尝试在加载MyApp::Schema::connect模块时调用MyApp::Model::Foo,并且它是否成功将取决于其他软件包的加载顺序。因此,在use MyApp::Schema;包的顶部写MyApp::Model::Foo可能会解决您的问题。


可能解决您问题的另一件事是您的架构的延迟初始化。使用函数调用替换模型中$schema的所有实例,例如schema(),并包含以下代码:

my $_schema;
sub schema {
    $_schema //= MyApp::Schem->connect("dbi:SQLite:data.db")
}

现在,您的架构对象会在需要时初始化一次,并且可能在您的应用程序所依赖的所有其他相关模块已经加载后进行初始化。

答案 2 :(得分:0)

我在Catalyst::Model::DBIC::Schema中读到我们可以使用$ self-> schema来从任何地方访问db schema。所以这个变种很好用:

sub bar {
  my ($self) = @_;
  my $schema = $self->schema;
}