人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

PHPについて質問です。

カンマで区切った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差し上げます。
よろしくお願いします。

●質問者: hanabusatsukasa
●カテゴリ:インターネット ウェブ制作
✍キーワード:.jpg CSV dB EmEditor GF
○ 状態 :終了
└ 回答数 : 5/5件

▽最新の回答へ

1 ● kurukuru-neko
●100ポイント

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>
◎質問者からの返答

うまくいきました!

百数件もデータがあると縦にページが長くなるのですが、30件ずつで分割はできませんか?

1?30 31?60 61?90 91?120

のように次の30件ごとに分割はどうなるでしょうか?


2 ● kurukuru-neko
●1000ポイント

前の回答に価格でソートする機能を追加すると

先頭の部分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");
};

3 ● Mook
●100ポイント

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>&nbsp;</td>\n";
 }
 print "</tr>\n";
 }
 print "</table>\n";
?>
◎質問者からの返答

文章、注釈もシンプルでとても勉強になりました。

もしよろしければ、ページ分割もご教授いただければ幸いです。


4 ● Mook
●100ポイント

はてなのページのように、左上にページのリンクを表示した例です。

読み込みや、表示の部分を前回の回答から少し変更したので、見づらくなったかもしれませんが、参考になるでしょうか。

<?
// 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を指すので、利用すると便利だと思います。

御参考までに。

◎質問者からの返答

理解するのに少し時間がかかりそうですが、貴重な学習の時間になりそうです。

ありがとうございました。


5 ● tobeoscontinue
●100ポイント
<?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 .= '&nbsp;<a href="'.$_SERVER['SCRIPT_NAME'].'?p='.$p.'">'.$p.'</a>&nbsp;';
 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 &amp;&amp; $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']) &amp;&amp; is_numeric($_GET['p']) &amp;&amp; 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にするので行ごとに数が異なっても問題ありません。

◎質問者からの返答

解説までいただけ、わかりやすく感じました。

時間をかけ、自分のものにしていきたいと思います。

ありがとうございます。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ