ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

Perlコミュのperl 初心者です。

  • mixiチェック
  • このエントリーをはてなブックマークに追加
flexigridを使用して。
かっこいいtableを作りたいです。

http://chines.com.ar/flexigrid/grid.p
↑にデモとソースがあったので、マネてみたのですが、結果が返ってきません。
どなたか、解説していただきたいです。

作ったソース grid.plとtemplate_flexigrid.htm
grid.plを実行しても、何も返ってきませんでした。エラーは、起きていないようです。
DBにも接続できています。


grid.pl
※※※※※※※※※※※※※※※※※※
#!/usr/bin/perl

use CGI;
use CGI::Carp qw (fatalsToBrowser);
use DBI;
use JSON;
use Template;
use Env;
use strict;
use warnings;
use vars qw ($q $tt $dbh);
use lib '.';

init();
grid_data() if ($q->param('mode') and $q->param('mode') eq 'grid_data');
main();

sub main {

my $vars = {
title => 'Flexigrid Perl Demo',
script_name => $ENV{SCRIPT_NAME},
};

print $q->header('text/html');
$tt->process('template_flexigrid.htm', $vars) || die $tt->error(), "\n";
exit;

}

sub grid_data {

my @rows;
my @bind;

my $where = '';

my $query = $q->param('query') || '';
my $qtype = $q->param('qtype') || '';
my $page = $q->param('page');
my $limit = $q->param('rp');
my $sort = $q->param('sortname');
my $order = $q->param('sortorder');

my $offset = ($page -1) * $limit;

if ($query) {
$where = "where $qtype like ?";
$query = '%' . $query . '%';
push @bind, $query;
}

my $sql = qq~select SQL_CALC_FOUND_ROWS

id,
iso,
name,
printable_name,
iso3,
numcode

from country

$where

order by $sort $order

limit $offset,$limit
~;

my $h = $dbh->prepare($sql) or die $DBI::errstr;
$h->execute(@bind) or die $DBI::errstr;

my %r;
my @c = @{ $h->{NAME_lc} };

$h->bind_columns( \( @r{ @c } ));

while ($h->fetch) {

my @cell;

$r{default} = ($r{iso} eq 'AR') ? 1 : 0;

foreach (qw (iso name printable_name iso3 numcode default)) {
push @cell, $r{$_}
}

push @rows, {
id => $r{id},
cell => [ @cell ]
};

}
$h->finish;

my $result = {
page => $page,
total => _total(),
rows => [ @rows ]
};

print $q->header('text/x-json');
print to_json($result);
exit;

}

sub _total {

my $h = $dbh->prepare('SELECT FOUND_ROWS() as total');
$h->execute;
my $row = $h->fetchrow_hashref;

return $row->{total};

}

sub init {

$q = new CGI;

unless (defined $tt) {

$tt = new Template({
INCLUDE_PATH => $ENV{DOCUMENT_ROOT} . './',
INTERPOLATE => 0,
}) or die "$Template::ERROR\n";

}

unless (defined $dbh) {

$dbh = DBI->connect('DBI:mysql:database=test;host=', 'test', 'test', {
RaiseError => 0,
PrintError => 1,
AutoCommit => 1
}) or die $DBI::errstr;

}

}

END {

$dbh->disconnect

}

template_flexigrid.htm
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>

<head>

<title>[% title %]</title>

<link rel="stylesheet" type="text/css" href="css/flexigrid/flexigrid.css">
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="flexigrid.js"></script>

<style>

.flexigrid div.fbutton .add
{
background: url(css/images/add.png) no-repeat center left;
}

.flexigrid div.fbutton .delete
{
background: url(css/images/close.png) no-repeat center left;
}

</style>

</head>

<body>

<h1>[% title %]</h1>
<table id="flex1" style="display:none"></table>

<script type="text/javascript">

$("#flex1").flexigrid (
{
url: '[% script_name %]',
dataType: 'json',
params : [
{name: 'mode', value: 'grid_data'}
],
colModel : [
{display: 'ISO', name : 'iso', width : 40, sortable : true, align: 'center', process: procMe},
{display: 'Name', name : 'name', width : 180, sortable : true, align: 'left'},
{display: 'Printable Name', name : 'printable_name', width : 120, sortable : true, align: 'left'},
{display: 'ISO3', name : 'iso3', width : 130, sortable : true, align: 'left', hide: true},
{display: 'Number Code', name : 'numcode', width : 80, sortable : true, align: 'right'},
{display: ' ', name : 'default', width : 40, sortable : true, align: 'center', process: showDefault}
],
buttons : [
{name: 'Add', bclass: 'add', onpress : test},
{name: 'Delete', bclass: 'delete', onpress : test},
{separator: true}
],
searchitems : [
{display: 'ISO', name : 'iso'},
{display: 'Name', name : 'name', isdefault: true}
],
sortname: "iso",
sortorder: "asc",
usepager: true,
title: 'Countries',
useRp: true,
rp: 15,
showTableToggleBtn: true,
width: 700,
height: 200
}
);

function procMe(celDiv,id)
{
$(celDiv).click
(
function ()
{
alert(this.innerHTML);
}
);

}

function showDefault(cel,id) {

var v = cel.innerHTML;

if (v == '1') {
cel.innerHTML = '<img src="images/default.png" width="16" height="16">';
}
else {
cel.innerHTML = '';
}

}

function test(com,grid) {

if (com=='Delete')
{
confirm('Delete ' + $('.trSelected',grid).length + ' items?')
}
else if (com=='Add')
{
alert('Add New Item');
}
}

</script>

<p><a href="grid.txt">Source</a></p>

<pre>
[% env %]
</pre>

</body>

</html>

コメント(46)

> たくろー さん

テンプレート名には,相対パスが許されていないみたいです.
grid.pl と同じパスに置いたのならば,

use FindBin;

しておいて,

$tt = new Template({
  INCLUDE_PATH => $ENV{DOCUMENT_ROOT} . './',
  INTERPOLATE => 0,
}) or die "$Template::ERROR\n";



$tt = new Template({
  INCLUDE_PATH => $FindBin::RealBin . '/',
  INTERPOLATE => 0,
}) or die "$Template::ERROR\n";

とかにしたら動くかと思います.

とり急ぎ.
>clairvy様

もう絶対パスを書きました。
こんな感じで

INCLUDE_PATH => '/usr/home/hogehoge/cgi-bin/',



一難去ってまた一難。

[Thu Feb 4 12:15:50 2010] [error] [client 192.168.0.0.10] file permissions deny server execution: /usr/home/webmaster2005/cgi-bin/js/flexigrid.js

なんか、このテンプレートってcgi-bin以下に置いてはならんかった?の?
'/usr/home/hogehoge/cgi-bin/'  の設定でない?

apacheの設定ファイルの設定を変えるか、
flexigrid.jsを、どこか別のデレクトリィに置くとよいと思いますよ。
泣き顔たくろーさんでも無理なら、私はもうダメかもです。

DBから値は取得できているのですが、
取得した値を、テンプレートに渡せていないっぽいんですよね。

PLが悪いのかテンプレートが悪いのかも、わかんないです泣き顔
> マナミ☆☆☆ さん

以下のようなURL で,ブラウザから直接アクセスしてみてはいかがでしょうか?
テンプレート関係無くデータを grid.pl から取得できます.

http://<hostname>/grid.pl?mode=grid_data;page=1;rp=15;sortname=id;sortorder=asc

これで取れていないなら,
DB から取得する → ブラウザへデータを JSON 形式で返す.
の間で問題がある可能性がありますね.
>clairvyさん
教えていただいた、URLでアクセスしたら。
<h1>Software error:</h1>
<pre>Undefined subroutine &main::to_json called at************grid.pl line 117.
</pre>
<p>
giving this error message
and the time and date of the error.
エラーになりました。
ご指摘通り、JSON形式で返す箇所に、問題があるのですね。

print to_json($result);
↑が117行目の記述です。

あー、もうチョット頑張ってみます。
有難うございました。
これでイイかどうかは別として、、、
 
コマンドラインから、
perl -e 'use JSON; $p=[1]; print to_json($p);'
と実行してみて同じエラー(Undefined subroutine &main::to_json called)は出ますか?
 
同じエラーが出るとした場合、以下を試すとどうでしょうか?
perl -e 'use JSON; $p=[1]; print JSON::to_json($p);'
>あささんへ
grid.plの

to_json($p);'

JSON::to_json($p);'

に変更したら、取得できるようになりました。

これで、解決いたしました。to_json($p);'が×な理由は、自分で調査いたします。

ありがとうございました。非常に感謝いたします。泣き顔

今回、ご協力して頂いた
たくろーさん
clairvyさん
giko鯖管@非友愛さん
rdonさん、
あささん、誠にありがとうございました。

まだまだ、未熟者ですので、またいろいろとご質問をするかもしれないですが、

その時は、よろしく御願いいたします。

自分自身でも、perlの勉強を頑張ります。

本当にありがとうございました。
>マナミ☆☆☆様

途中で放り投げてしまって申し訳ない。
とりあえず解決して良かったっす。
すいません。私セッカチさんでした。そして私すっごくお馬鹿です。
だから、もう少し教えて欲しい事があります。
お願いばかりで、ごめんなさい。

実は文字化けで悩んでいます。

文字が化けちゃうんです。私の化粧よりも激しく化けちゃうんです。

文字が化けている箇所は、テンプレートのhtmlの文字全部とDBから取得した結果です。

htmlはcharset=Shift_JISにしてます。

DBからの取得時は $dbh->do("set names sjis");
で取得しているので化けていませんでした。
dbの取得結果とjsonの結果はログにて化けていない事を確認しました。

すいません、よろしくお願い致します。
> htmlはcharset=Shift_JISにしてます。

これはテンプレートで設定しているのですか?
また、設定内容は以下のようなものですか?
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">

あとCGI.pmの絡みで、grid.plの中の、
print $q->header('text/html');
ココを、
print $q->header(-type=>'text/html', -charset=>'Shift_JIS');
とすると、もしかしたら幸せになれるかもしれません。
# 確証は無いですが。
>あささん
早速、ありがとうございます。

<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
↑をテンプレートに設定しています。

print $q->header(-type=>'text/html', -charset=>'Shift_JIS');
↑ありがとうございます。htmlの文字化けがこれで直りました。

あとは、DBの値だけが化けています。
DBの値が化けてんのかなぁ?

なんだろ?mysqlでujisとかになってんのかな?

mysqlに対して
show variables like 'character_set%';
とかやると、なんて返ってきますかね?
JSON::to_json に渡す文字列は,decode 済みでなければならないようです.
また,JSON は,Unicode である必要がありそうです.

以下修正例です.
template_flexigrid.htm は,SJIS にする.

grid.pl は,先頭あたりに以下を追加して,
  use Encode;

データを取ってくる100行目あたりで,foreach の中を
  foreach (qw (iso name printable_name iso3 numcode default)) {
    push @cell, $r{$_}

  foreach (qw (iso name printable_name iso3 numcode default)) {
    my $value = decode('sjis', $r{$_});
    push @cell, $value;
にして,

to_json のあたりを(120行目あたり)
  print $q->header('text/x-json');
  print to_json($result);

  print $q->header(-type => 'text/x-json', -charset => 'UTF-8');
  print to_json($result, {utf8 => 1});
にしてみてはいかがでしょうか?

一応,完全なソースも置いておきます.
- http://gist.github.com/294232#file_grid.pl
>clairvyさん
clairvyさんのご指摘通りにしたら、直りました。
やばいです。めちゃめちゃ、嬉しいです。
ありがとう、ございます。これで、先に進めそうです。感動泣き顔

>あささん
解決できました。ありがとうございました。

>たくろーさん
文字化け解決できました。

mysqlに対して
show variables like 'character_set%'; をすると。

character_set_client latin1
character_set_connection latin1
character_set_database utf8
character_set_filesystem binary
character_set_results latin1
character_set_server utf8
character_set_system utf8
character_sets_dir /usr/local/mysql-src-5.1.22/share/mysql/charsets/
が返ってきます。
以上です。
問題が解決したようで良かったです.

参考にした情報を上げておきます.

JSON 形式について
- perldoc JSON
- http://www.json.org/json-ja.html
- http://blogs.wankuma.com/kacchan6/archive/2007/04/12/71235.aspx
- http://www.ietf.org/rfc/rfc4627.txt

MySQL - DBI - DBD::mysql 文字コード関連
- http://d.hatena.ne.jp/a666666/20090826/1251270979
- http://wota.jp/ac/?date=20061011

decode (utf8 flag) - Devel::Peek について
- http://d.hatena.ne.jp/tokuhirom/20080408/1207619640

以上です.
あ〜。DBの文字コードはutf8だったようで問題なかったんですね。

解決したようでなによりです。

clairvyさんすげぇ。
> たくろー さん
ありがとうございます.

補足として,MySQL だと TABLE や COLUMN にも CHARSET を指定できると思いますので,
SHOW VARIABLES だけから,UTF8 かどうか判断するのは尚早かと思います.

# たぶん latain1 のcolumn にも,データとしてならSJIS のデータが入るかも.
# 普通はやりませんが.

まぁ,それはどうでもいいとして,
問題点がどこかを発見することが一番難しい.ということですかね.
>マナミさん
勝手にソースを参考にさせてもらいました。スイマセンあせあせ

便乗して質問させて下さい。

grid.pl を呼び出すときに、引数を渡しているのですが、取得できません。

呼び出し方
grid.pl?title=xxxx;testID=yyyyy;

titleはmainメソッドで使用したい。
testIDはgrid_dataメソッドで使用したいです。

どなたか、教えてくださいexclamation ×2
 my $value = $q->param('testID');
とか
 my $value = $q->param('title');

みたいにすれば,変数 $value に値が入るのではないでしょうか?
聞きたかったことと違っていたらすみません.
>clairvyさん
さっそっく、有難うございます。
聞きたかった事はあっていますよexclamation ×2

my $value = $q->param('testID');
と記述しても取得できないです。意味がわかんないですexclamation ×2

griddataメソッドの
my $order = $q->param('sortorder'); の下部に
my $value = $q->param('testID'); を記載ししました。


sortorderとかは、テンプレートからわたしてます。
でも、testIDはgrid.plの呼び出し時に渡してるから、そこら辺がからんでるのかなと思ってます。

わかんないです。
すみません.データの渡し方について確認させてください.

> grid.pl を呼び出すときに、引数を渡しているのですが、取得できません。
>
> 呼び出し方
> grid.pl?title=xxxx;testID=yyyyy;

とあるのですが,これはブラウザからは,
 .../grid.pl?title=xxxx
でアクセスしていて,
テンプレートの,JavaScript の flexigrid() 関数の引数 params の値で,
 params : [
  {name: 'mode', value: 'grid_data', testID: 'yyyy'}
 ],
のようにしているということでしょうか?
それとも単にブラウザから,
 .../grid.pl?title=xxxx;testID=yyyy
のようにアクセスしているのでしょうか?

もしこれ以外の方法でデータを渡そうとしているのでしたら,
どうやってやろうとしているかを教えて頂ければ助かります.
URLの引数を取るならurl_param()を使います。

my $value = $q->url_param('testID');
>clairvyさん
単にブラウザから,
 .../grid.pl?title=xxxx;testID=yyyy で渡しています。

>あささん
my $value = $q->url_param('testID'); だとエラーになっちゃいます。

もう一つ質問です。
./grid.pl?title=xxxx;testID=yyyyとアクセスした結果を
my $buffer = $ENV{'QUERY_STRING'};
で取得できたのですが。

1回目のアクセスと2回目のアクセスの値が同じだと、取得できません。

1回目:grid.pl?title=xxxx;testID=yyyy
2回目:grid.pl?title=xxxx;testID=yyyy
↑2回目取得できない

1回目:grid.pl?title=xxxx;testID=yyyy
2回目:grid.pl?title=www;testID=aaaa
↑1回目と2回目の値が違うので取得できる。

キャッシュとかそこらへんが関係してるのでしょうか?
あああ、すみません、param()はQUERY_STRINGの内容も取りこめましたね、、、
url_param()は、formからくるSTDINとQUERY_STRINGを分別したい時に使うものでした。
ということで、url_param()では解決しませんでした。
 
本題ですが、 QUERY_STRING環境変数はどこで取得しているでしょうか。
詳細が把握できていないのでハズしているかもしれませんが、
grid_data() if ($q->param('mode') and $q->param('mode') eq 'grid_data');
とあるように、grid_data()はテンプレートの処理プロセスで用いられているようです。
この時のプロセスに、当初のQUERY_STRING環境変数の内容が渡されていないために色々と生じているような気がします。
 
さて、コレで解決するかどうかわかりませんが、、、
 
1)
grid_data() if ($q->param('mode') and $q->param('mode') eq 'grid_data');
ここを、
if ($q->param('mode') and $q->param('mode') eq 'grid_data'){
grid_data();
}
else{
# gridの生成プロセス以外の場合のみ以下をQUERY_STRINGから取得。
$title = $q->param('title');
$testID = $q->param('testID');
}
という具合にする。
 
2)
上記$titleと$testIDを、Templateのprocess経由で引き渡す。
my $vars = {
title => $title, # <- 変更
script_name => $ENV{SCRIPT_NAME},
testID => $testID, # <- 追加
};

3)
process()で渡される変数にあわせて、
params : [
{name: 'mode', value: 'grid_data'}
],
部分を、
params : [
{name: 'mode', value: 'grid_data', title: [% title %], testID: [% testID %]}
],
等として、パラメータがテンプレート経由でgrid_data()に渡るようにする。
 
という感じにしてみると、いかがでしょうか。
当方、これらをすぐに試せる環境にないため、コレであっているかどうかわかりません、あしからず(^_^;
> レイナ さん

返答ありがとうございます.

> 単にブラウザから,
>  .../grid.pl?title=xxxx;testID=yyyy で渡しています。

なるほど,この場合,main() 関数には,title , testID の値は渡りますが,
grid_data() 関数にはデータは渡らない筈です.
main() は,URL からデータを渡せるとして,
grid_data() 関数にデータを渡したい場合,
以下が参考になるかもしれません.

テンプレートの,JavaScript の flexigrid() 関数の引数 params の部分で,
渡すパラメータを指定する.
 params : [
   {name: 'mode', value: 'grid_data'}
  , {name: 'testID', value: 'yyyy'}
 ],

こうすることで,grid_data() 内で param('testID') ができる
かと思います.

参考に私が書いたソースをリンクしておきます.
- grid.pl - http://gist.github.com/294232#file_grid.pl
- template_flexigrid.htm - http://gist.github.com/raw/294232/ddc5f1687493834488efa1d903779e84a41e27d0/template_flexigrid.htm
>あささん、clairvyさん
ありがとうございます、
お二方のやり方で試してみます。

後で、ご報告いたします。
>clairvyさん
ちょっと、質問です。

 params : [
   {name: 'mode', value: 'grid_data'}
  , {name: 'testID', value: 'yyyy'}
 ],
↑の記述だと、testIDの値がyyyyが固定になっちゃいます。

gird.pl
my $testID = $q->param('testID') || '';
↑の記述を追加する以外は、何か修正がいるのでしょうか?
>あささん
質問です。

1、2、3のやり方は、事前に、
QUERY_STRING環境変数を取得しておく必要があるのでしょうか?
my $buffer = $ENV{'QUERY_STRING'}; このような記述で。

それとも、
$title = $q->param('title');
↑この記述自体が QUERY_STRINGから環境変数を取得している事を示しているのでしょうか?

単に1,2,3の記述を追加しただけだと、全てうまくいきませんでした。

すいません。
URLの引数として、以下のように与えられていれば、
......../grid.pl?title=hogehoge

>$title = $q->param('title');
>↑この記述自体が QUERY_STRINGから環境変数を取得している事を示しているのでしょうか?

この方法で、$titleにhogehogeが得られるはずなのです。
すなわち、別途QUERY_STRING環境変数を見る必要は無いです。

1)、および2)、3)の工程で所望の値が取れてるかどうか確認してみてください。

1)の確認は取得された$titleの中身を適当なファイルに吐いてみるとかです。
とれてない場合は(取れない理由が思い当たりませんが)、init()の中で$title、$testIDを取ってみるとかですかね、、、
CGIのコンストラクタが呼ばれた後で、
if (!$q->param('mode') or $q->param('mode') ne 'grid_data'){
$title = $q->param('title');
$testID = $q->param('testID');
}

2)、3)の確認は、ブラウザでソース表示をしてみるとわかりやすいかもしれません。
書き換えたparams: のところに所望の値が入るかどうか。
あと、今ふと思ったのですが、3)の書き換えは、もしかすると、
params : [
{name: 'mode', value: 'grid_data', title: '[% title %]', testID: '[% testID %]'}
],
が正しいかもしれません。
>あささんへ
頭が悪くて申し訳ないです泣き顔

>この方法で、$titleにhogehogeが得られるはずなのです。
>すなわち、別途QUERY_STRING環境変数を見る必要は無いです。
理解しました。

init()で
my $title = $q->param('title');
my $testID = $q->param('testID');

と記載すると取得できました。

if ($q->param('mode') and $q->param('mode') eq 'grid_data'){
grid_data();
}
else{
$title = $q->param('title');
$testID = $q->param('testID');
open(OUT, "> ./debug.log");
print(OUT "$title ");
print(OUT "\n");
print(OUT "$testID");
print(OUT "\n");
close(OUT);
}
↑だと取得できませんでした。ログが空です。

init()で取得した結果を配列に入れてreturnしてもダメでした。
ドタバタして混乱させてしまい、ごめんなさい。テンプレートの修正は、
 params : [
   {name: 'mode', value: 'grid_data'},
   {name: 'testID', value: '[% testID %]'} , #<-こんな具合で行を追加
 ],
が正しかったです。

あと、use vars に、$titleと$testIDを追加してみてください。すみません、これ、忘れてました・・・

しかし、init()では取れるている、というのが不思議な感じですね。
ひとまず、init()に仕込んだdebug.log書き出しですが、これをif($q->param('mode')..)のelse部に(当初値を取ろうとした箇所に)設置し、ログを追記型(>>)で書き出してみると、何か傾向が掴めるかもしれません。
TO: レイナ さん

>   , {name: 'testID', value: 'yyyy'}
> ↑の記述だと、testIDの値がyyyyが固定になっちゃいます。
そうですね.どういう値を与えるかがわからなかったので,
とりあえず固定になっています.

> gird.pl
> my $testID = $q->param('testID') || '';
> ↑の記述を追加する以外は、何か修正がいるのでしょうか?
取り出すだけならば,上記を追加するだけかと思います.
testID というキィからは,どう使うかがわからなかったものですから.
私のソースだと,WHERE句で id と testID を比較してたりしますね.

もうちょっとやりたいことがわかれば,
近い例なども書けるかもしれません.
とりあえずは,「値を渡す」という部分ができるように考えていました.

以上です.
> レイナ さん

以下,見落していました.

> キャッシュとかそこらへんが関係してるのでしょうか?
ブラウザのキャッシュの可能性がありますね.
ブラウザのキャッシュを無効にすれば,
毎回ブラウザ → grid.pl への通信が行われると思います.

ログインすると、残り12件のコメントが見れるよ

mixiユーザー
ログインしてコメントしよう!

Perl 更新情報

Perlのメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング