簡単な掲示板(CSV形式で保存)

2009/05/21 バックスラッシュ(\)対策に、addslashes, stripslashes通すよう修正。
2009/05/11 defineの第一引数をシングルクォートで囲むよう修正。$addr -> $addressに修正。
4年生への課題を自分もやってみた。

要求仕様

  • XHTML形式で出力
  • CSV形式でデータ保存
  • 名前は10文字まで
  • メールアドレスは30文字まで
  • コメントは300文字まで

コード

M2の意地で頑張ってみた。

<?php
define('ENCODE', 'UTF-8');
define('CSV_FILE', 'ex1.csv');
define('NAME_MAX', 10);
define('ADDRESS_MAX', 30);
define('COMMENT_MAX', 300);

$name = $address = $comment = '';
$error = array();

function isValid($str, $type)
{
  global $error; // ただの$errorだとスコープがisValidになってしまう
  $len = mb_strlen($str, ENCODE);
  $mask = 0;

  switch ($type)
  {
    case 'name':
      if ($len == 0)
        $error['name'] = '必須項目です';
      else if (NAME_MAX < $len)
        $error['name'] = '長すぎます';
      else
        $mask = 1; // 001(2)
      break;

    case 'address':
      if ($len == 0)
        $error['address'] = '必須項目です';
      else if (ADDRESS_MAX < $len)
        $error['address'] = '長すぎます';
      else if (!filter_var($str, FILTER_VALIDATE_EMAIL))
        $error['address'] = '正しい形式になっていません';
      else
        $mask = 2; // 010(2)
      break;

    case 'comment':
      if ($len == 0)
        $error['comment'] = '必須項目です';
      else if (COMMENT_MAX < $len)
        $error['comment'] = '長すぎます';
      else
        $mask = 4; // 100(2)
      break;
  }

  return $mask;
}

function countUp()
{
  static $i = 0;
  return (++$i < 10) ? '0' . $i : $i;
}

function sanitize($str)
{
  return stripslashes(htmlentities($str, ENT_QUOTES, ENCODE));
}

function mail_to($name, $address)
{
  return '<a href="mailto:' . $address . '">' . sanitize($name) . '</a>';
}

// フォームからデータが送信されてきた
if (!empty($_POST))
{
  $name = $_POST['name'];
  $address = $_POST['address'];
  $comment = $_POST['comment'];
  $time = time();

  // 全ての検証を突破した(結果の論理積とって比較。全ビットが1なら 111(2) で 7(10) )
  if ((isValid($name, 'name') | isValid($address, 'address') | isValid($comment, 'comment')) == 7)
  {
    // ファイルを書き込みモードで開く
    if (($handle = fopen(CSV_FILE, 'a')) === false)
      die('can not open ex1.csv');

    // CSV形式で書き込み
    if(fputcsv($handle, array(addslashes($name), $address, $time, addslashes($comment))) === false)
      die('error fputcsv');

    // 一旦閉じないと反映されない
    fclose($handle);

    // 初期化
    $name = $address = $comment = '';
  }
}

// ファイルを読み込みモードで開く
if (($handle = fopen(CSV_FILE, 'r')) === false)
  die('can not open ex1.csv');
?>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
  <head>
    <meta http-equiv="Content-Style-Type" content="text/css" />
    <link rel="stylesheet" href="ex1.css" type="text/css" charset="utf-8" />
    <title>課題1</title>
  </head>
  <body>
    <h1>掲示板</h1>
    <ul>
    <?php while (($data = fgetcsv($handle)) !== false && !is_null($data[0])): ?>
      <li>
        <span class="num"><?php echo countUp() ?></span>
        <span class="name"><?php echo mail_to($data[0], $data[1]) ?></span>
        <span class="date"><?php echo date("Y年m月d日 H時i分s秒", $data[2]) ?></span>
      </li>
      <li>
        <p class="comment"><?php echo sanitize($data[3]) ?></p>
      </li>
    <?php endwhile; fclose($handle); ?>
    </ul>
    <div id="form_box">
      <form action="ex1.php" method="post">
        <table cellspacing="5">
          <tr>
            <td>
              <span>名前</span><br />
              <small>10文字まで</small>
            </td>
            <td>
              <?php if (isset($error['name'])): ?>
              <span class="error"><?php echo $error['name'] ?></span><br />
              <?php endif; ?>
              <span><input type="text" name="name" size="30" maxlength="30" value="<?php echo $name ?>"/></span>
            </td>
          </tr>
          <tr>
            <td>
              <span>メールアドレス</span><br />
              <small>30文字まで</small>
            </td>
            <td>
              <?php if (isset($error['address'])): ?>
              <span class="error"><?php echo $error['address'] ?></span><br />
              <?php endif; ?>
              <span><input type="text" name="address" size="30" maxlength="30" value="<?php echo $address ?>"/></span>
            </td>
          </tr>
          <tr>
            <td id="comment">
              <span>コメント</span><br />
              <small>300文字まで</small>
            </td>
            <td>
              <?php if (isset($error['comment'])): ?>
              <span class="error"><?php echo $error['comment'] ?></span><br />
              <?php endif; ?>
              <span><textarea name="comment" rows="8" cols="40"><?php echo $comment ?></textarea></span>
            </td>
          </tr>
        </table>
        <p id="submit_button"><input type="submit" value="送信" /></p>
      </form>
    </div>
  </body>
</html>