2009年10月18日日曜日

[Perl] mod_perl で Constants を操作する際の注意点

mod_perl で Constants を操作したときにはまったのでメモ。
#!/usr/bin/perl
use strict;
use warnings;

use CGI;
use Data::Dumper;

use constant {
    HASH_REF_LIST => [
        { id => 1 },
        { id => 2 },
        { id => 3 },
    ],
};

my $cgi = CGI->new();
my $id  = $cgi->param('id') || '';

# 定数をコピーしてから操作したので安全のつもり
my @array = @{HASH_REF_LIST()};
for (@array) {
    $_->{selected} = 1 if ($_->{id} == $id);
}

print $cgi->header;
print Dumper(\@array);
id クエリを受け取って、定数内のキーと一致すれば、
そのキーに selected フラグを付ける。
まあプルダウンメニューとかで使われそうなコードです。

これを mod_perl で適当に id を変えて実行していると気づきます。
id と一致していないキーに seleted が付く時があると。。

原因は @array に定数を完全コピーをしたつもりが、
定数内がリファレンスになっているので外側だけしかコピーできていない点。

リファレンスを操作しちゃっているので、
当然それもキャッシュされて残ってしまいます。

解決策は、Storable::dclone とかでクローンを作るか、
自前でデリファレンスしてコピーする。

よく見ればわかりますが、なかなか気づきにくいのでご注意を。

0 件のコメント: