カンマで区切った100行程度のCSVデータのうち画像のアドレスのある物のみweb上に表示したいと思っています。
ifを使い場所や定価を条件検索は作ることができました。ネックなのはレンタルサーバーがDBが使えないためPHPしか使えません。
それらの条件検索をかけた後に「画像のある物のみweb上で画像と店舗名を表示させたい」とおもっています。
その際どのようなPHP文章を書けばよいでしょうか。
店舗名,価格,定価(yen),場所(m),商品画像
電器店a,12000,20000,200,001.gf
電器店b,10000,20000,300,002jpg
電器店c,11000,20000,80,054.jpg
電器店d,15000,20000,100,なし
電器店e,13000,20000,20,005.gif
イメージ的には
http://images.google.com/images?hl=ja&client=opera&rls=en&hs=4Zz&q=%E3%83%A4%E3%83%95%E3%83%BC&btnG=Google+%E6%A4%9C%E7%B4%A2&lr=&ie=UTF-8&oe=UTF-8&um=1&sa=N&tab=wi
こんな感じで商品を表示させたいのです。
emeditorでプログラムをを書きxammpでテストし独自ドメインサイト(DB機能なし)にアップしています。
良回答者には1000pt差し上げます。
よろしくお願いします。
EUCの文字コードでファイル
data.csvにデータが1行
の最大文字数1000文字程度で
データが保存されていると過程
した場合
データは3件単位で折り返し
<?php mb_language("Japanese"); mb_internal_encoding("EUC-JP"); $data = array(); $handle = fopen("data.csv","r"); if( !$handle ) { } else { while( ($csvdata = fgetcsv($handle,1024,",")) != FALSE ){ $csvnum = count($csvdata); if( $csvnum < 4 ) continue; if( $csvdata[4] == "なし" ) continue; $data[] = $csvdata; }; fclose($handle); $data_num = sizeof($data); $round_num=3; # echo "<html>\n"; echo "<body>\n"; echo "<table>\n"; for( $i=0; $i < $data_num; $i += $round_num ) { $jmax=( ($i+$round_num) < $data_num ) ? ($i+$round_num) : $data_num; echo "<tr>\n"; for( $j = $i ; $j < $jmax; $j++ ) { $val=$data[$j]; echo "<td><img src=\"".$val[4] ."\"></td>\n"; }; echo "</tr>\n"; echo "<tr>\n"; for( $j = $i ; $j < $jmax; $j++ ) { $val=$data[$j]; echo "<td><b>".$val[0] ."</b></td>\n"; }; echo "</tr>\n"; }; echo "</table>\n"; echo "</body>\n"; echo "</html>\n"; }; ?>
実行するとこんなかんじ
<html> <body> <table> <tr> <td><img src="001.gf"></td> <td><img src="002jpg"></td> <td><img src="054.jpg"></td> </tr> <tr> <td><b>電器店a</b></td> <td><b>電器店b</b></td> <td><b>電器店c</b></td> </tr> <tr> <td><img src="005.gif"></td> </tr> <tr> <td><b>電器店e</b></td> </tr> </table> </body> </html>
前の回答に価格でソートする機能を追加すると
先頭の部分PHP以下に
<?php
比較関数を追加
# 昇順でソート function pricecmp($a, $b) { # CSVの2番目の販売価格でソート if ($a[1] == $b[1]) { return 0; } return ($a[1] < $b[1]) ? -1 : 1; }
データを読み込んだあとに
fclose($handle); $data_num = sizeof($data);
比較処理を追加
# Sort if( $data_num > 0 ) { usort($data,"pricecmp"); };
CSV がdata.csv が次のようにあったとしたら
電器店a,12000,20000,200,001.gf 電器店b,10000,20000,300,002jpg 電器店c,11000,20000,80,054.jpg 電器店d,15000,20000,100,なし 電器店e,13000,20000,20,005.gif
下記のような感じでどうでしょうか。
<? // 画像を横に並べる数 define( "COL_NUM", 3 ); // CSV ファイルを読み込み $handle = fopen("data.csv", "r"); while (($row = fgetcsv($handle, 1000, ",")) !== FALSE) { $data[] = array( 'shop'=>$row[0] ,'priceA'=>$row[1], 'priceB'=>$row[2], 'place'=>$row[3], 'picture'=>$row[4] ); } fclose($handle); // 画像データを並べる print "<table width = \"80%\">\n"; foreach ($data as $key => $row) { if( strcmp( $row['picture'], 'なし' ) != 0 ) { // 画像の有無の判定 if ( $rowCount % COL_NUM ==0 ) print "<tr>\n"; print "<td align=\"center\">\n"; print "<img src=\"".$row['picture']."\"><br>\n"; print $row['shop']."<br>\n"; print $row['priceA']."<br><br><br>\n"; print "</td>\n"; $rowCount++; if ( $rowCount % COL_NUM == 0 ) print "</tr>\n"; } } // 画像データがCOL_NUM の倍数でなかったら整合をとる if ( $rowCount % COL_NUM != 0 ) { for ( $i=$rowCount % COL_NUM ; $i<COL_NUM ; $i++ ) { print "<td> </td>\n"; } print "</tr>\n"; } print "</table>\n"; ?>
文章、注釈もシンプルでとても勉強になりました。
もしよろしければ、ページ分割もご教授いただければ幸いです。
はてなのページのように、左上にページのリンクを表示した例です。
読み込みや、表示の部分を前回の回答から少し変更したので、見づらくなったかもしれませんが、参考になるでしょうか。
<?
// 1ページの数
define( "PAGE_NUM", 30 );
// 画像を横に並べる数
define( "COL_NUM", 6 );
// CSV ファイルを読み込み
$handle = fopen("data.csv", "r");
while (($row = fgetcsv($handle, 1000, ",")) !== FALSE) {
if ( strcmp( $row[4], 'なし' ) != 0 ) { // 'なし' はスキップ
$data[] = array( 'shop'=>$row[0], 'priceA'=>$row[1],
'priceB'=>$row[2], 'place'=>$row[3], 'picture'=>$row[4] );
$dataNum++;
}
}
fclose($handle);
// URL オプションを処理
if ( empty($_GET['page']) == false ) {
$dispPage = $_GET['page'];
} else { // 指定がないときは先頭ページ
$dispPage = 1;
}
// ページの表示
print "<table width = \"80%\">\n";
print '<tr><td colspan="'.COL_NUM.'" align="right">'."\n";
for ( $i=1 ; $i<=( ( $dataNum - 1 ) / PAGE_NUM + 1 ) ; $i++ ) {
if ( $dispPage == $i ) {
print " {$i} ";
} else {
print " <a href=".$_SERVER['PHP_SELF']."?page=$i>{$i}</a> ";
}
}
print "</td></tr>\n";
// 画像データを並べる
print "<table width = \"80%\">\n";
$index = PAGE_NUM * ($dispPage - 1);
for ( $i=0 ; $i<PAGE_NUM ; $i++, $index++ ) {
if ( $i % COL_NUM ==0 ) print "<tr>\n";
if ( $index < $dataNum ) {
print "<td align=\"center\">\n";
print "<img src=\"".$data[$index]['picture']."\"><br>\n";
print $data[$index]['shop']."<br>\n";
print $data[$index]['priceA']."<br><br><br>\n";
print "</td>\n";
$rowCount++;
} else {
print "<td> </td>\n";
}
if ( $i % COL_NUM == (COL_NUM - 1) ) print "</tr>\n";
}
// 画像データがCOL_NUM の倍数でなかったら整合をとる
if ( $rowCount % COL_NUM != 0 ) {
for ( $i=$rowCount % COL_NUM ; $i<COL_NUM ; $i++ ) {
print "<td> </td>\n";
}
print "</tr>\n";
}
print "</table>\n";
?>
$_SERVER['PHP_SELF'] は自分自身のURLを指すので、利用すると便利だと思います。
御参考までに。
理解するのに少し時間がかかりそうですが、貴重な学習の時間になりそうです。
ありがとうございました。
<?php define ('PAGE_SIZE', 30); function contents_html($chunk) { $contents = ''; foreach ($chunk as $row) { $contents .= '<table width="100%"><tr>'; foreach ($row as $csv) $contents .= '<td align="center">'. '<img src="'.$csv[4].'"><br>'.$csv[0].'<br>'.$csv[1].'('.$csv[2].')'. '</td>'."\n"; $contents .= '</tr></table>'; } return $contents; } function page_html($max) { $contents = ''; if (1 < $max) for ($p = 1; $p <= $max; $p++) { $contents .= ' <a href="'.$_SERVER['SCRIPT_NAME'].'?p='.$p.'">'.$p.'</a> '; if ($p < $max) $contents .= '|'; } return '<center>'.$contents.'</center>'; } function array_getcsv($name) { $csv = file($name); $data = array(); foreach ($csv as $item) $data[] = explode(',', trim($item)); return $data; } function array_csv_delete($csv) { $data = array(); foreach ($csv as $item) if (count($item) == 5 && $item[4] != 'なし') $data[] = $item; return $data; } function cmp_csv1($a, $b) { return ($a[1] == $b[1]) ? 0 : ($a[1] > $b[1]) ? 1 : -1; } $title = "電器店map"; mb_internal_encoding("utf-8"); $csv = array_csv_delete(array_getcsv("data.csv")); $pm = intval(count($csv)/PAGE_SIZE)+1; $p = (isset($_GET['p']) && is_numeric($_GET['p']) && intval($_GET['p']) <= $pm ) ? intval($_GET['p'])-1 : 0; usort($csv, "cmp_csv1"); $csv = array_slice($csv, $p*PAGE_SIZE, PAGE_SIZE); ?> <html><head> <title><?= $title ?></title> <meta http-equiv="Content-Type" content="text/html; charset=<?= mb_internal_encoding() ?>"/> </head> <body> <h1><?= $title ?></h1> <table width="100%"> <tr><td height="30" bgcolor="#bbcced"></td></tr> <tr><td ><?= contents_html(array_chunk($csv,4)) ?></td></tr> <tr><td height="30" valign="center" bgcolor="#bbcced"><?= page_html($pm) ?></td></tr></table> </body></html>
contents_html()は主要なhtmlを吐き出します。$chunkは二次元の配列で横方向(行)で一つの<table>で構成されます。
<td>の部分を希望にそうように変更する必要があるでしょう。
page_html()はページ用のアンカーhtmlを吐き出します。
?p=という単純なものです。
array_getcsv()はcsvのファイルを読みこんで二次元の配列にします。
fgetcsv()のほうがいいかもしれません。
array_csv_delete()は画像が無いものは削除するためのものです。
cmp_csv1($a, $b)は価格でソートするのに使う関数です。
mb_internal_encoding("utf-8");
エンコーディングについてはあまり考慮していません。問題があれば変更して下さい。スクリプトで'なし'を使っているのとdata.csvのエンコードは変換していないので合わせる必要があります。私の場合はutf-8で統一してテストしました。
$csv = array_csv_delete(array_getcsv("data.csv"));
data.csvを読みこんでarray_csv_deletで必要ないものを削除しています。
$pは何ページを表示するかを示し、0から始まります。1ページにいくつ表示するかはPAGE_SIZEで指定します。
usort($csv, "cmp_csv1");
価格で並べ換えします。
$csv = array_slice($csv, $p*PAGE_SIZE, PAGE_SIZE);
array_slice()で表示に必要な部分だけ取り出します。
contents_html(array_chunk($csv,4))
array_chunk()で4っつずつ区切ります。これで一行に4っつずつ表示されることになります。凝るならwidthを求めて一行にいくついれるか決めてもいいでしょう。contents_html()は行ごとにtableにするので行ごとに数が異なっても問題ありません。
解説までいただけ、わかりやすく感じました。
時間をかけ、自分のものにしていきたいと思います。
ありがとうございます。
うまくいきました!
百数件もデータがあると縦にページが長くなるのですが、30件ずつで分割はできませんか?
1~30 31~60 61~90 91~120
のように次の30件ごとに分割はどうなるでしょうか?