首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 單一表單處理新增與編輯:統一邏輯與檔案上傳技巧

     編輯:PHP 相關知識

核心概念

以 id 參數判斷模式:有 id = 編輯,無 id = 新增。同一支程式處理顯示表單與接收 POST。

完整控制器範例

<?php
// ArticleController.php
class ArticleController {
    private PDO $pdo;

    public function __construct(PDO $pdo) { $this->pdo = $pdo; }

    public function createOrEdit(): void {
        $id = $_GET['id'] ?? null;
        $isEdit = $id !== null;

        // 1. 取得現有資料 (編輯模式)
        $data = [
            'title' => '',
            'content' => '',
            'cover' => '',
        ];
        if ($isEdit) {
            $stmt = $this->pdo->prepare("SELECT * FROM articles WHERE id = ?");
            $stmt->execute([$id]);
            $data = $stmt->fetch(PDO::FETCH_ASSOC) ?: $data;
        }

        // 2. 處理 POST
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $this->handlePost($id, $isEdit);
            return; // 已重導向
        }

        // 3. 顯示表單
        $this->renderForm($data, $isEdit);
    }

    private function handlePost(?int $id, bool $isEdit): void {
        $title = trim($_POST['title'] ?? '');
        $content = trim($_POST['content'] ?? '');
        if (!$title || !$content) {
            $this->renderForm(['error'=>'標題與內容必填'], $isEdit);
            return;
        }

        // 檔案上傳處理
        $coverPath = $data['cover'] ?? ''; // 保留舊圖
        if (!empty($_FILES['cover']['name'])) {
            $upload = $this->uploadCover($_FILES['cover']);
            if ($upload['success']) {
                $coverPath = $upload['path'];
                // 刪除舊檔 (編輯模式)
                if ($isEdit && $data['cover'] && file_exists($data['cover'])) {
                    @unlink($data['cover']);
                }
            } else {
                $this->renderForm(['error'=>$upload['error']], $isEdit);
                return;
            }
        }

        // 寫入資料庫
        if ($isEdit) {
            $stmt = $this->pdo->prepare("UPDATE articles SET title=?, content=?, cover=? WHERE id=?");
            $stmt->execute([$title, $content, $coverPath, $id]);
        } else {
            $stmt = $this->pdo->prepare("INSERT INTO articles (title, content, cover) VALUES (?, ?, ?)");
            $stmt->execute([$title, $content, $coverPath]);
        }

        header('Location: /articles');
        exit;
    }

    private function uploadCover(array $file): array {
        $allow = ['image/jpeg','image/png','image/webp'];
        if (!in_array($file['type'], $allow)) return ['success'=>false, 'error'=>'圖片格式不支援'];
        if ($file['size'] > 2*1024*1024) return ['success'=>false, 'error'=>'檔案不可超過 2MB'];

        $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
        $name = bin2hex(random_bytes(8)) . ".$ext";
        $dir = __DIR__ . '/../public/uploads/covers/' . date('Y/m');
        if (!is_dir($dir)) mkdir($dir, 0755, true);
        $dest = "$dir/$name";

        if (move_uploaded_file($file['tmp_name'], $dest)) {
            return ['success'=>true, 'path'=>"/uploads/covers/" . date('Y/m') . "/$name"];
        }
        return ['success'=>false, 'error'=>'上傳失敗'];
    }

    private function renderForm(array $data, bool $isEdit): void {
        extract($data); // $title, $content, $cover, $error
        include __DIR__ . '/../views/article_form.php';
    }
}

視圖檔 (article_form.php)

<form method="post" enctype="multipart/form-data">
    <?php if (!empty($error)): ?><div class="alert"><?= h($error) ?></div><?php endif; ?>
    
    <div>
        <label>標題</label>
        <input name="title" value="<?= h($title) ?>" required />
    </div>
    
    <div>
        <label>內容</label>
        <textarea name="content" required><?= h($content) ?></textarea>
    </div>
    
    <div>
        <label>封面圖</label>
        <?php if ($cover): ?>
            <img src="<?= h($cover) ?>" style="max-height:100px" />
            <label><input type="checkbox" name="remove_cover" /> 移除現有圖片</label>
        <?php endif; ?>
        <input type="file" name="cover" accept="image/*" />
    </div>
    
    <button type="submit"><?= $isEdit ? '更新' : '發布' ?></button>
    <a href="/articles">取消</a>
</form>

關鍵技巧總結

情境處理方式
編輯時不換圖保留資料庫原 cover 路徑,不處理 $_FILES
編輯時換新圖上傳新檔 → 刪除舊檔 → 更新路徑
編輯時清除圖勾選 remove_cover → 刪除檔案 → 存空字串
新增失敗保留輸入POST 後重新 renderForm,帶入 $_POST 值
防止重複提交PRG 模式:POST 成功後 header('Location: ...') 導向 GET
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved