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

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

超初心者向けCGI講座コミュのスキンファイルを利用したCGIの構築

  • mixiチェック
  • このエントリーをはてなブックマークに追加
よろしくお願いします。

現在ページ作成中で、オーソドックスな左メニュー右本文ページを作っています。
その中にデータベースCGIを動作させたかったので、データベースCGIのデザインを改造中です。
ページデザインを考えてデータベース内にも左メニューを掲載しようと思っています。
しかし、この左メニューが変わる可能性があります。その為、データベースの表示部分をスキン(テンプレート)で表示できないかと考えています。

さて、幾つかのスキン対応CGIを見たのですが、うまく理解できませんでした。

私が確認したのは以下のものです。

##########スキンファイルを開く##########
 open(FILE,"./skin.html")||&error("No skin.html");
  @skin=<FILE>;
  $skin="@skin";
  close(FILE);

  ($form_skin,$main_skin)=split(/##header##/,$skin);
  ($main_skin,$end_skin)=split(/##end##/,$main_skin);

  foreach $simple(@allbody){
  ($date,$name,$text)=split(/<>/,$simple);
  $q_skin=$main_skin;
  $q_skin =~ s/#name/$name/s;
  $q_skin =~ s/#text/$text/s;
  $q_skin =~ s/#date/$date/s;
  $a_skin="$a_skin$q_skin";
 }

#############HTML出力
 $skin="$form_skin$a_skin$end_skin";
 open(FILE,">./bbs.html")||&error("Save Error");
 print FILE "$skin";
 close(FILE);
}

スキンを開いてsplitで割って(ここがうまく理解できません)情報を格納して最終的に結合して出力、と言う方式ですよね。
この
私としては...
スキンを開く
  ↓
splitで各レコードが入るまでとその後に分割
  ↓
表示部分のいわゆる「&headre」「&footer」の位置に「&"スキン上部"」「&"スキン下部"」として表示

と言う流れにしたいのですが…
この場合、どのようにしたら良いでしょうか?

コメント(15)

これを書き込んだ後に気が付いたのですが、
例えば、スキンhtmlファイルの分割したい部分に「##split##」と記入、
CGIの方でスキンファイルを開いた後
($skin_header,$skin_footer)=split(/##split##/,$skin);

として、表示部分のそれぞれ「&headre」「&footer」を「$skin_header」「$skin_footer」に変えてあげればOKとかでしょうか?

おっと、
print "$skin_header\n";
ですね。

この考えで間違ってないですか?
はじめまして。

> 表示部分のいわゆる「&headre」「&footer」の位置に
> 「&"スキン上部"」「&"スキン下部"」として表示

この部分がいまいちわからないのですが、「&headre」と「&footer」はサブルーチンではなく置換指示子(置換の対象となる文字列)のことですね?

テンプレートファイルをsplitで分割することは必須処理ではありませんが、余計なループ処理をさせないと言う意味では分割してもいいのかもしれませんね。

テンプレートファイルがヘッダー・ボディ・フッターの要素で構成されているのであれば、

($skin_header,$skin_body,$skin_footer)=split(/##split##/,$skin);

などといった感じになると思います。


> 表示部分のそれぞれ「&headre」「&footer」を
> 「$skin_header」「$skin_footer」に変えてあげればOKとかでしょうか?

テンプレートファイルと「$skin_header」「$skin_footer」の中味がどのようなものなのかがわからないので断言できませんが、だいたいそんな感じになると思います。
返答ありがとうございます。

説明が足りなかったです、ごめんなさい。

スキンとなるページはテーブルで構成されていて

┌───────┐
│  表題   │
├─┬─────┤
│こ│ここに  │
│こ│CGIで │
│に│表示   │
│メ│     │
│ニ│     │
│ュ│     │
│| │     │
└─┴─────┘
こういう構成になってます。
で、「ここにCGIで表示」の部分で2分割(##split##を記入)しようと思ってます。   
で、前を$skin_header、後ろを$skin_footerに格納・表示です。
こんな考えでOKでしょうか?
こんな感じのことを目指しているのでしょうか?

--- skin.html ---
<html>
・・・
<table><tr>
<td>ここにメニュー</td>
<td>
##split##
<p>ここに #name CGIの #text 本文を #date 表示</p>
##split##
</td>
</tr></table>
・・・
</html>

--- cgi/script ---
(略)
# 上側、本文のテンプレ、下側に分割
($skin_header,$skin_body,$skin_footer)=split(/##split##/,$skin);

# テンプレを使って本文を作る
$a_skin = '';
foreach $simple(@allbody)
{
  ($date,$name,$text)=split(/<>/,$simple);
  
  # 本文テンプレ
  $q_skin = $skin_body;

  # 置換
  $q_skin =~ s/#name/$name/s;
  $q_skin =~ s/#text/$text/s;
  $q_skin =~ s/#date/$date/s;

  # 本文全体
  $a_skin .= $q_skin;
}

(略)

# 上側、本文全体、下側を出力
print FILE $skin_header;
print FILE $a_skin;
print FILE $skin_footer;
HTML::Template
Template::Toolkit

この辺は使えない?
返答ありがとうございます。

>れい さん
スキン利用を考えてまず何かサンプルになるCGIが無いかを探してその時に見つけたのがその方式でした。

ただ、データベース表示部分が結構面倒なことをしていて(いや、皆さんには面倒なことではないのかもしれませんが…)それをまた崩すのは大変だと感じました。

そこで、上記の2分割方式を選択しました。

┌─────────┐
│   表題    │
├─┬───────┤
│こ│┌─────┐│
│こ││##split##.││
│に│└─────┘│
│メ│       │
│ニ│       │
│ュ│       │
│| │       │
└─┴───────┘

テンプレートをこのように作成して、
$skin_headerに<header>部分からデータベース直前の表(<TD>)まで、$skin_footerにデータベース直後の表(</TD>)から</html>までを格納しました。

で、本文表示部分を
print "$skin_header\n";

foreach $data〜〜

print "$skin_footer\n";
としました。

やってみたのですが、1つエラーが出てしまいました。
このままだと、500エラーが出ます。
表示部分に
print "Content-type: text/html\n\n";
print "$skin_header\n";

foreach $data〜〜

print "$skin_footer\n";
とすることで無事解決しました。

正常動作しているようなので大丈夫だとは思うのですが…
下手な方法かもしれませんが、変な事はしてないでしょうか?

>R.F.D. さん
それもサンプルを探している時に見たのですが、私にはちょっと難しかったのでまたの機会に良く見ておきます。

とりあえず、動作中なので質問終了としますが、明らかに変な事をしているとかの指摘がありしたらお願いします。

皆さんありがとうございました。
…
と思ったのですが、問題発生です!

メニュー部分なのですが、今までSSIを利用してデータベースのレコード数(ジャンルごとに分けてそのジャンルごとにいくつデータがあるか)を掲載していました。いかし、それが表示しません。

いろいろと調べてみると、CGI上でSSIは動作しないとの事。
と言うことで、今までカウントを処理していたCGIからレコード数をカウントする部分だけを抜き取り、
if($genre == 1){$ken1++;}
elsif($genre == 2){$ken2++;}
と言う感じで
$ken1から$ken10までを作りました。
テンプレートの表示部分
<!--#include virtual="./count.cgi?mode=bg&bg=1" -->
を
($ken1)
に変更したのですが、ページ上には($ken1)と表示するだけで、内容を表示しません。
ためしにデータベース表示部分

&count;
print "$skin_header\n";
print "$ken1\n"; ←この位置
foreach $data〜〜

print "$skin_footer\n";
に持ってくると正常に表示します。

テンプレート上に変数を表示するのにはどうしたら良いのでしょうか?
SSIはCGI以前のサーバーの機能なので、CGIの中ではもちろん動作しませんね。

全体像がわからないのでなんともいえませんが、テンプレートに適当な置換指示子を書いて、カウントデータと置換すればよいだけではないのでしょうか・・・?
この手のやり取りでいつも思うのですが、情報が断片的&小出しだと回答者はさまざまなパターンを推測しつつ答えざるを得ないので、適切なアドバイスも得られにくいと思います。回答者の立場に立って、ある程度まとまった情報を公開したほうが解決も早いと思いますよ。

仮に、僕がまーべりっくさんに「お腹がいたいのですがなぜでしょうか?」と聞いても、まーべりっくさんもそれだけの情報では診断のしようがないと思いますので、ご理解いただけますよね。
何度もすみません。
質問する前に自分でチャレンジしろって声が聞こえてきそうですが、上記の件は解決したように思える状態です。
$skin_heads =~ s/#a_ken1#/$a_ken1/s;
これで、変換することが出来ました。

さて、またまた問題発生です。

>Kei さんのご指摘の通り、小出しにしても意味が無いと感じましたので、ソースをそのまま日記に張りました。
http://mixi.jp/view_diary.pl?id=355109549&owner_id=2891126
そのままコピペなので、見づらいと思います。適当なエディタに貼り付けての確認をお願いします。

さて、現段階で「次の20件」をクリックすると、件数表示部分が「#a_ken1#」に戻ってしまいます。
どうやらスキンファイルを開く部分などを飛ばしているようです。(途中だけループ?)これを解決したいのですが、どのようにしたら良いでしょうか?
ウワァァ━━━━━。゚(゚´Д`゚)゚。━━━━━ン!!!!

スレ汚してホントごめんなさい。
途中で動作しなくなって原因が判らなくならない様に別ファイル名でやってたのですが、「次の20件」のリンクが旧ファイルにになってました。
(旧ファイルがいらないと思って削除したため判明)
もちろん、リンク先を変えることで正常動作しました。


ホントにごめんなさい。
<(_ _)>
先に挙げたHTML::Templateですが、
モジュールさえ既にインストールされている状態なら、
自力でテンプレートシステムを作るより楽だと思います(笑)


use HTML::Template;
my $template = HTML::Template->new(
  'filename' => 'template.html',
);
$template->param(
  'DATA1'=> $data1,
  'DATA2'=> $data2,
);
print "Content-Type: text/html\n\n";
print $template->output;

Perl部分なんて、基本これだけですもん(笑)
HTML::Templateは本当に楽ですね。僕は配布CGIのソースに変数を埋め込むのにも使っていますが、とても重宝しています。
ソースそのものにですか!?
Web上でフォームに必要事項を記入すれば、各種設定が埋まった状態で出力されるとか……?

ログインすると、みんなのコメントがもっと見れるよ

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

超初心者向けCGI講座 更新情報

超初心者向けCGI講座のメンバーはこんなコミュニティにも参加しています

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