SO。
对于我遇到的具体问题,标题可能过于笼统。
我有一个连接到SQLite数据库的Perl脚本。在运行期间,我执行了很多数据库操作,例如SELECT,INSERT,UPDATE等。我将每个数据库操作包装在它自己的子例程中(主要是为了隐藏SQL语句和结果集的任何其他处理)。
每次我需要调用此数据库操作子例程之一时,我想使用相同的数据库处理程序对象,所以我一直在做的是将数据库处理程序对象作为参数传递。例如:
my $dbh = DBI->connect( "dbi:SQLite:dbname=db.db", "", "") or die;
sub select_from_systems {
my $dbh = shift;
return $dbh->selectcol_arrayref("SELECT hostname FROM systems");
}
正如旁注,我正在使用Perl DBI。
我只是想知道是否有更聪明的方法来执行此操作,因此我不必将数据库处理程序对象作为参数传递。
我想避免全局变量,我不认为它们是瘟疫,在这种情况下它可能是合理的,但仍然。
非常感谢任何帮助或见解。
问候。
答案 0 :(得分:4)
使您的模块面向对象。这仍然会将句柄作为参数传递,但语法更好。
package MyConnection;
sub new {
my $class = shift;
my $dbh = DBI->new(@_);
bless \$dbh, $class;
}
sub select_from_systems {
my $self = shift;
$$self->selectcol_arrayref(...);
}
然后:
my $db = MyConnection->new(@credentials);
...;
my $result = $db->select_from_systems;
为了对对象建模,我在这里使用了一个简单的标量引用,但你可能想要传统的基于散列的OO(或者只是使用Moose)。
答案 1 :(得分:3)
这听起来像你应该考虑使用面向对象的Perl。如果您不熟悉面向对象编程,那么其中一个好处就是您可以拥有一组函数,这些函数都可以对某些常见数据进行操作(在本例中为数据库引用)。
对OO Perl的一个很好的低级别介绍是perlootut on Perldoc,尽管当你在Perl中进行大规模的面向对象编程时,使用像Moose这样的模块似乎很流行。
现在,在幕后,Perl仍然绕过对象(某种类型的引用,通常是散列引用),并且使用基本的OO Perl,函数本身仍然需要显式处理它。但是,它使调用语义更好,如下所示:
my $database_object = new DatabaseObject("dbi:SQLite:dbname=db.db");
$database_object->select_from_systems();
相应的函数定义类似于:
package DatabaseObject;
sub new {
my $class = shift;
my $dbpath = shift;
my $dbh = DBI->connect( $dbpath, "", "") or die;
my $self = {_dbh => $dbh};
bless $self, $class;
return $self;
}
sub select_from_systems {
my $self = shift;
return $self->{_dbh}->selectcol_arrayref("SELECT hostname FROM systems");
}
答案 2 :(得分:2)
如果您真的希望数据库处理程序是Singleton(例如每个Perl进程一个),您可以:
对全局变量使用our
作用域别名。这并不像OO方法那样整洁,但它通常可以很好地完成,没有任何缺点 - 这是少数几种推荐our
的罕见情况之一。
将其设置为our
,但为其创建类级别(例如非对象)setter和getter方法。
将其设置为真正的单身人士。这里讨论的技术是:How can I implement a singleton class in perl?