You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP与jQuery实现CSV文件展示、新增及删除功能技术问询

解决方案:PHP + AJAX 实现CSV表格的增删功能

CSV更新方案选择结论

小数据量下优先选整体重写CSV,逻辑简单不易出错;大数据量(上千行级)再考虑单行处理。你的场景是逐行渲染表格,大概率数据规模不大,整体重写能避免单行追加时的格式混乱、删除时的行定位偏差等问题,可靠性更高。


功能实现步骤

一、前端HTML/JS(含表格渲染)

假设CSV有「姓名、邮箱、电话」三列,调整页面结构如下:

<!-- 核心表格 -->
<table id="csvTable">
  <thead>
    <tr>
      <th>姓名</th>
      <th>邮箱</th>
      <th>电话</th>
      <th>操作</th>
    </tr>
  </thead>
  <tbody>
    <!-- PHP渲染已有数据行 -->
    <?php
    $csvFile = 'data.csv';
    if (($handle = fopen($csvFile, 'r')) !== FALSE) {
      while (($data = fgetcsv($handle, 1000, ',')) !== FALSE) {
        echo "<tr>";
        echo "<td>" . htmlspecialchars($data[0]) . "</td>";
        echo "<td>" . htmlspecialchars($data[1]) . "</td>";
        echo "<td>" . htmlspecialchars($data[2]) . "</td>";
        echo "<td><button class='deleteBtn' data-row='" . htmlspecialchars(implode(',', $data)) . "'>删除</button></td>";
        echo "</tr>";
      }
      fclose($handle);
    }
    ?>
  </tbody>
</table>

<!-- 新增行输入区 -->
<div id="addRowArea">
  <input type="text" id="inputName" placeholder="姓名">
  <input type="email" id="inputEmail" placeholder="邮箱">
  <input type="text" id="inputPhone" placeholder="电话">
  <button id="saveNewRow">保存</button>
</div>

<script>
// 新增行逻辑
document.getElementById('saveNewRow').addEventListener('click', function() {
  const name = document.getElementById('inputName').value.trim();
  const email = document.getElementById('inputEmail').value.trim();
  const phone = document.getElementById('inputPhone').value.trim();
  
  if (!name || !email || !phone) {
    alert('请填写完整信息');
    return;
  }

  // 发送AJAX请求
  fetch('csv_handler.php', {
    method: 'POST',
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    body: `action=add&name=${encodeURIComponent(name)}&email=${encodeURIComponent(email)}&phone=${encodeURIComponent(phone)}`
  })
  .then(res => res.text())
  .then(result => {
    if (result === 'success') {
      // 前端插入新行
      const tbody = document.getElementById('csvTable').querySelector('tbody');
      const newRow = document.createElement('tr');
      newRow.innerHTML = `
        <td>${htmlEscape(name)}</td>
        <td>${htmlEscape(email)}</td>
        <td>${htmlEscape(phone)}</td>
        <td><button class='deleteBtn' data-row='${encodeURIComponent(`${name},${email},${phone}`)}'>删除</button></td>
      `;
      tbody.appendChild(newRow);
      // 清空输入框
      document.getElementById('inputName').value = '';
      document.getElementById('inputEmail').value = '';
      document.getElementById('inputPhone').value = '';
    } else {
      alert('保存失败,请重试');
    }
  })
  .catch(err => console.error('请求出错:', err));
});

// 删除行逻辑
document.querySelectorAll('.deleteBtn').forEach(btn => {
  btn.addEventListener('click', function() {
    const rowData = decodeURIComponent(this.getAttribute('data-row')).split(',');
    const name = rowData[0];
    const email = rowData[1];
    const phone = rowData[2];

    if (confirm('确定删除该行?')) {
      fetch('csv_handler.php', {
        method: 'POST',
        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        body: `action=delete&name=${encodeURIComponent(name)}&email=${encodeURIComponent(email)}&phone=${encodeURIComponent(phone)}`
      })
      .then(res => res.text())
      .then(result => {
        if (result === 'success') {
          // 前端移除该行
          this.parentElement.parentElement.remove();
        } else {
          alert('删除失败,请重试');
        }
      })
      .catch(err => console.error('请求出错:', err));
    }
  });
});

// HTML字符转义辅助函数
function htmlEscape(str) {
  return str.replace(/[&<>"']/g, match => {
    const escapeMap = {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#039;'};
    return escapeMap[match];
  });
}
</script>

二、后端处理脚本(csv_handler.php)

负责接收AJAX请求,用整体重写方式更新CSV:

<?php
$csvPath = 'data.csv';

// 初始化CSV(无文件则创建表头)
if (!file_exists($csvPath)) {
  $header = ['姓名', '邮箱', '电话'];
  $handle = fopen($csvPath, 'w');
  fputcsv($handle, $header);
  fclose($handle);
}

// 读取现有CSV数据到数组
$csvContent = [];
if (($handle = fopen($csvPath, 'r')) !== FALSE) {
  while (($row = fgetcsv($handle, 1000, ',')) !== FALSE) {
    $csvContent[] = $row;
  }
  fclose($handle);
}

$action = $_POST['action'] ?? '';

switch ($action) {
  case 'add':
    $newRow = [
      $_POST['name'] ?? '',
      $_POST['email'] ?? '',
      $_POST['phone'] ?? ''
    ];
    // 过滤空行
    if (!empty(array_filter($newRow))) {
      $csvContent[] = $newRow;
      // 重写CSV
      $handle = fopen($csvPath, 'w');
      foreach ($csvContent as $row) fputcsv($handle, $row);
      fclose($handle);
      echo 'success';
    } else echo 'error';
    break;

  case 'delete':
    $targetRow = [
      $_POST['name'] ?? '',
      $_POST['email'] ?? '',
      $_POST['phone'] ?? ''
    ];
    // 过滤掉目标行
    $updatedContent = array_filter($csvContent, fn($row) => $row !== $targetRow);
    // 重写CSV
    $handle = fopen($csvPath, 'w');
    foreach ($updatedContent as $row) fputcsv($handle, $row);
    fclose($handle);
    echo 'success';
    break;

  default:
    echo 'invalid_action';
    break;
}
?>

关键注意事项

  • 权限配置:确保PHP对CSV文件有读写权限(可设置chmod 644或755,依服务器环境调整)。
  • 数据校验:实际使用时需增强输入校验(比如邮箱格式、电话格式),防止恶意输入破坏CSV结构。
  • 并发安全:多用户操作场景下,需在读写文件时加锁,比如在fopen后调用flock($handle, LOCK_EX),操作完成后调用flock($handle, LOCK_UN)。

内容的提问来源于stack exchange,提问作者T. Pluess

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 14:43:30