【问题标题】:How do I access a specific return value from the CDBI::Search function?如何从 CDBI::Search 函数访问特定的返回值?
【发布时间】:2012-05-30 04:38:43
【问题描述】:

我正在使用DB::CDBI 类来访问我们应用程序中的数据库。我们的项目使用面向对象的 Perl。

package LT::LanguageImport;
use strict;
use warnings;
use base 'Misk5::CDBI';

__PACKAGE__->table( 'english_text_translation' );
__PACKAGE__->columns( Primary => qw/english language translation/ );
__PACKAGE__->columns( Essential => qw/english language translation/ );
__PACKAGE__->has_a( english => 'LT::EnglishLanguage' );

在这种情况下,我应该检查表中是否存在一行。我在 CDBI 调用中使用内置搜索 API。

sub find_translation {
    my $translation_exists_r_not = $class->search(
        english     => $english,
        language    => $language,
        translation => $translation
    );
    return;
}

$translation_exists_r_not 正在根据搜索中给出的输入获取预期值。如果该行存在,则_data 将使用行详细信息进行更新。

$translation_exists_r_not = bless({
        '_data' => [
            {
                'language'    => 'polish',
                'translation' => 'Admin',
                'english'     => 'admin'
            }
        ],
        '_place'  => 0,
        '_mapper' => [],
        '_class'  => 'LT::LanguageImport'
    },
    'Class::DBI::Iterator'
);

如果该行不存在,那么我会得到这样的返回值。

$translation_exists_r_not = bless({
        '_data'   => [],
        '_place'  => 0,
        '_mapper' => [],
        '_class'  => 'LT::LanguageImport'
    },
    'Class::DBI::Iterator'
);

我想根据搜索结果从这个子 find_translation 返回 translation 的值。我无法为此获得最佳状态。

我尝试将_data 复制到一个数组中,但我不确定如何继续。因为_data 将是一个空的arrayref,而另一个条件它将在arrayref 内有一个hashref。

my @Arr = $translation_exists_r_not->{'_data'};

【问题讨论】:

  • @daxim 感谢您编辑问题
  • 当你有对象时,你不应该通过解引用直接获取数据;这称为打破封装。相反,在对象上调用适当的方法和访问器。代码示例没有用,因为您没有显示LT::LanguageImport 的类定义。 Edit your question 添加缺失类的代码。
  • 我非常同意 daxim 在这里的评论。这肯定不是您编写 OO Perl 的方式。

标签: perl class-dbi


【解决方案1】:

CDBI 的search 方法将返回一个迭代器,因为根据您的条件可能会返回多行。

如果您知道只有一行符合您的条件,您想使用retrieve 方法,即:

if (my $translation_exists_r_not = $class->retrieve(
    english     => $english,
    language    => $language,
    translation => $translation
)){
    return [$translation_exists_r_not->translation,
            'Misk5::TranslationAlreadyExists']
}
else {
    return [ '', undef ]
}

如果您的搜索可以返回多行,并且您只对真实性感兴趣,那么同样,不要在 CDBI::Iterator 内部翻找,而是使用它的方法:

my $translation_exists_r_not = $class->search(
    english     => $english,
    language    => $language,
    translation => $translation
); # returns an iterator
if ($translation_exists_r_not){
    my $first = $translation_exists_r_not->first;
    return [ $first->translation, 'Misk5::TranslationAlreadyExists' ]
}

看看perldoc Class::DBIperldoc Class::DBI::Iterator。 CDBI 有优秀的文档。

【讨论】:

    【解决方案2】:

    我想我找到了解决方案。感谢任何试图解决它的人。

    my @req_array      = %$translation_exists_r_not->{_data};
    my $length_of_data = '9';
    foreach my $elem (@req_array) {
        $length_of_data = @{$elem};
    }
    

    现在检查数组的长度。

    if ($length_of_data == 0) {
        $error = '';
        $result = [undef, $error];
    }
    

    现在检查它是否是一个。

    if ($length_of_data == 1) {
        my @result_array = @{%$translation_exists_r_not->{_data}};
        my $translation  = $result_array[0]{'translation'};
        $error = 'Misk5::TranslationAlreadyExists';
        $result = [$translation, $error];
    }
    return @$result;
    

    【讨论】:

    • 正如 daxim 所说,您真的不应该摆弄 CDBI 迭代器对象的内部结构。看我的回答...
    猜你喜欢
    • 2021-07-20
    • 2015-09-14
    • 1970-01-01
    • 2022-09-29
    • 1970-01-01
    • 1970-01-01
    • 2018-10-10
    • 2018-06-08
    • 2010-12-28
    相关资源
    最近更新 更多