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差し上げます。
よろしくお願いします。

回答の条件
  • 1人20回まで
  • 登録:
  • 終了:2007/03/16 23:06:39
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答5件)

id:kurukuru-neko No.1

回答回数1844ベストアンサー獲得回数155

ポイント100pt

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>
id:hanabusatsukasa

うまくいきました!

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

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

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

2007/03/11 18:23:31
id:kurukuru-neko No.2

回答回数1844ベストアンサー獲得回数155

ポイント1000pt

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

先頭の部分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");
};
id:Mook No.3

回答回数1314ベストアンサー獲得回数393

ポイント100pt

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";
?>
id:hanabusatsukasa

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

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

2007/03/11 18:23:47
id:Mook No.4

回答回数1314ベストアンサー獲得回数393

ポイント100pt

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

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

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

御参考までに。

id:hanabusatsukasa

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

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

2007/03/16 23:04:14
id:tobeoscontinue No.5

回答回数220ベストアンサー獲得回数59

ポイント100pt
<?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にするので行ごとに数が異なっても問題ありません。

id:hanabusatsukasa

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

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

ありがとうございます。

2007/03/16 23:05:10
  • id:kurukuru-neko
    バグってますね。
    };
    echo "</tr>\n";

    の後ろに (2箇所)
    for( ; $j < ($i+$round_num); $j++ ) {
    echo "<td>&nbsp;</td>\n";
    };

    -----------------------
    画像なしの場合は、無視していますが
    画像なしで表示するのであれば

    if( $csvdata[4] == "なし" ) continue;
    を消して

    echo "<td><img src=\"".$val[4] ."\"></td>\n";
    の部分で"なし"の場合の画像をダミー画像
    に変える
    if( $val[4] == "なし" ) {
    echo "<td><img src=\"nashi.gif\"></td>\n";
    } else {
    echo "<td><img src=\"".$val[4] ."\"></td>\n";
    };

    表示幅は、round_num=3;
    を変更する。

    テーブルの部分は、実際の表示する
    構成でアレンジが必要

  • id:tobeoscontinue
    バグがありました。
    $pm = intval(count($csv)/PAGE_SIZE)+1;

    $pm = intval((count($csv)+PAGE_SIZE-1)/PAGE_SIZE);
    の方がいいでしょう。
    ちょうど割り切れる時に、一つ余計なページのアンカーを生成してしまうので。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません