kamatamaudon
@kamatamaudon

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

編集画面の作成 php

解決したいこと

編集画面でテキストと画像を登録したい

テキストと画像を編集できるシステムを作成しています。

項目が2つある場合、1つ目は登録済みのまま、2つ目は画像を削除して新しくファイルを読み取って登録しようとしたところ、取り込んだ2つ目の方のファイルが、1つ目のcontent(内容)とセットでテーブルに保存されました。

機能としては、
追加ボタンを押すと、入力欄とファイル読み取りフォームのセットが追加されます(上限なし)
編集画面のため、すでに登録済みのデータが表示されておりますが、画像を削除したり登録しなおしたりできます。
入力欄とファイル欄両方が空だった場合はそのセットは登録しないようにしたいです。
解決方法を教えて下さい。

html

<form action="" method="post" enctype="multipart/form-data">
<input type="hidden" name="id" value="<?= h($id) ?>">
<table>  
    <tr>
        <th>内容</th>
        <td>
         <div id="formContainer">
            <?php if (isset($_POST['content'])): ?>
                <?php foreach ($_POST['content'] as $k => $c): ?>
                    <div class="form_add">
                        <textarea name="content[]" <?= $k == 0 ? 'required':''?>><?= isset($c) ? h($c) : '' ?></textarea>
                            <div class="imageContainer"> 
                                <input type="file" name="image[]" accept="image/*" <?= $k == 0 ? 'required':''?>>
                            </div>
                        </div>
                    <?php endforeach; ?>
                <?php else: ?>
                    <?php foreach ($lists as $k => $v): ?>
                        <div class="form_add">
                            <textarea name="content[]" <?= $k == 0 ? 'required':''?>><?= h($v['content']) ?></textarea>
                            <div class="imageContainer"> 
                                <?php if (!empty($v['img_name_origin2'])): ?>
                                    <?= h($v['img_name_origin2']) ?>
                                    <button type="button" class="delete-button" data-file="<?= $v['img_name2'] ?>" data-id="<?= $v['blog2_id'] ?>">ファイルを削除</button>
                                <?php else: ?>
                                    <input type="file" name="image[]" accept="image/*"  <?= $k == 0 ? 'required':''?>>
                                <?php endif; ?>
                            </div>
                        </div>
                    <?php endforeach; ?>
                <?php endif; ?>
            </div>
    
            <button type="button" class="add-button" onclick="addSubheading()">+ 追加</button>
        </td>                                            
    </tr>             
</table>     

<?php foreach ($errors as $error): ?>
    <p><?= h($error); ?></p>
<?php endforeach; ?>
<input type="submit" name="submit" value="保存">
 

または、問題・エラーが起きている画像をここにドラッグアンドドロップ

javascript

<!-- 項目増やすスクリプト -->
<script>
  function addSubheading() {
      const formContainer = document.getElementById("formContainer");

      // 新しい項目を作成
      const newRow = document.createElement("div");
      newRow.className = "form_add";
      newRow.innerHTML = `
          <textarea name="content[]"></textarea>
          <input type="file" name="image[]" accept="image/*">
      `;

      // 既存の項目の下に追加
      formContainer.appendChild(newRow);
  }
</script>

<!-- 内容画像削除 -->
<script>
document.addEventListener('DOMContentLoaded', function() {
    document.getElementById('formContainer').addEventListener('click', async function(e) {
        if (e.target.classList.contains('delete-button')) {
            e.preventDefault();

            if (!confirm("ファイルを削除しますか?")) {
                return;
            }

            const fileName = e.target.dataset.file;
            const contentId = e.target.dataset.id;
            const imageContainer = e.target.closest('.imageContainer');  // クラス名を修正

            try {
                const response = await fetch('edit.php', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                    body: `file_index2=${encodeURIComponent(fileName)}&blog2_id=${encodeURIComponent(contentId)}`
                });

                const result = await response.json();

                if (result.success) {
                    // 削除成功時のUI変更
                    imageContainer.innerHTML = '<input type="file" name="image[]" accept="image/*">';
                } else {
                    alert(result.message || 'ファイルの削除に失敗しました');
                }
            } catch (error) {
                console.error('Error:', error);
                alert('エラーが発生しました');
            }
        }
    });
});</script>

php

$uploadDir = "../../file/"; // アップロードディレクトリ
$maxFileSize = 10 * 1024 * 1024; // 最大ファイルサイズ10MB

// 内容画像削除処理
if (isset($_POST['file_index2'], $_POST['blog2_id'])) { 
    $fileName = $_POST['file_index2'];
    $blog2_id = $_POST['blog2_id'];
    $response = ['success' => false];
    $filePath = $uploadDir . $fileName;

    try {
        $mysqli->begin_transaction();

        $stmt = $mysqli->prepare("UPDATE blog2 SET img_name_origin2 = NULL, img_name2 = NULL WHERE blog2_id = ?");
        $stmt->bind_param('i', $blog2_id);
        $stmt->execute();

        if ($stmt->affected_rows === 0) {
            throw new Exception('データベースの更新に失敗しました');
        }

        $mysqli->commit();

        if (file_exists($filePath)) {
            unlink($filePath);
        }

        $response = ['success' => true, 'message' => 'ファイルが削除されました'];
    } catch (Exception $e) {
        $mysqli->rollback();
        $response['message'] = 'データベースエラー: ' . $e->getMessage();
    }

    header('Content-Type: application/json');
    echo json_encode($response);
    exit;
}

$blog_id = $_POST['id'];
// データを取得(blog2)
$stmt = $mysqli->prepare("SELECT * FROM blog2 WHERE blog_id = ?");
$stmt->bind_param('s', $blog1_id);
$stmt->execute();
$res = $stmt->get_result();
$lists = $res->fetch_all(MYSQLI_ASSOC);
$stmt->close();
//更新
if ($_SERVER['REQUEST_METHOD'] == "POST" && isset($_POST['submit'])) {
$blog_id = $_POST['id']; // blog1_idを取得

// 既存データを取得($existingDataがない場合に処理を行う)
$stmt = $mysqli->prepare("SELECT * FROM blog2 WHERE blog_id = ?");
$stmt->bind_param('i', $blog1_id);
$stmt->execute();
$existingEntries = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
$stmt->close();  // ステートメントを閉じる

// 既存データのマッピング(blog2_id => 画像情報)
$existingData = [];
foreach ($existingEntries as $entry) {
    $existingData[$entry['blog2_id']] = [
        'img_name2' => $entry['img_name2'],
        'img_name_origin2' => $entry['img_name_origin2']
    ];
}

// 新規データ登録用の準備
$stmt = $mysqli->prepare("INSERT INTO blog2 (blog_id, content, img_name2, img_name_origin2) VALUES (?, ?, ?, ?)");

foreach ($_POST['content'] as $k => $content) {
    // hidden フィールドで送信されたインデックスを取得
    $imageIndex = isset($_POST['image_index'][$k]) ? $_POST['image_index'][$k] : null;

    // 画像情報の初期化
    $img_name2 = isset($_POST['existing_image'][$k]) && $_POST['existing_image'][$k] ? $_POST['existing_image'][$k] : null;
    $img_name_origin2 = $img_name2;

    // content と image の両方が空ならスキップ
    if (empty(trim($content)) && empty($_FILES['image']['name'][$k]) && !$img_name2) {
        continue;
    }

    // $existingData がない場合(画像の変更がない場合)または $_FILES['image'] が存在する場合のみ処理
    if (empty($existingData[$imageIndex]) || !empty($_FILES['image']['name'][$k])) {
        // 画像がアップロードされている場合
        if (!empty($_FILES['image']['name'][$k])) {
            $fileTemp = $_FILES['image']['tmp_name'][$k];
            $fileName = $_FILES['image']['name'][$k];

            // 画像アップロード処理
            $uploadName = myUpload3($fileTemp, $uploadDir, 'image');

            if ($uploadName) {
                $img_name2 = $uploadName;
                $img_name_origin2 = $fileName;
            } else {
                throw new Exception("画像のアップロードに失敗しました: index $k");
            }
        }
    }

    // データを登録
    $stmt->bind_param('isss', $blog_id, $content, $img_name2, $img_name_origin2);
    $stmt->execute();
}

$stmt->close();  // 最後にステートメントを閉じる
            if (empty($errors)) {
                $mysqli->commit();
                $_SESSION[$session_name]['blog'] = [
                    'title' => $title,
                    'content' => $_POST['content'],
                ];
                header("Location: e_comple.php");
                exit();
            } else {
                $mysqli->rollback();
            }            

        } catch (Exception $e) {
            $mysqli->rollback();
            die('データベースエラー: ' . $e->getMessage());
        }
    }
}


//ファイルアップロード関数
function myUpload3($tmpName, $path, $name) {

    // var_dump($_FILES[$name]['name'][0]);exit;
    // ファイル名を現在の日時+ランダム文字列で作成
    $ext = pathinfo($_FILES[$name]['name'][0], PATHINFO_EXTENSION);
    $upfileName = date('ymdhis') . uniqid('_') . '.' . $ext;

    // ファイルを指定のフォルダに移動
    if (move_uploaded_file($tmpName, $path . $upfileName)) {
        chmod($path . $upfileName, 0644);
        return $upfileName;
    }

    return false;
}


初心者でわからないことが多く、申し訳ないのですが、よろしくお願いいたします

0

2Answer

バリデーションっていうのかな?

テキスト内容とファイル名が空だったら submit しない。という JavaScript を書けば良いのではないでしょうか

空とかじゃなくても、入力した値が期待しているものかどうか、バリデーションするコードは必ず実装したほうが良いと思います。

なにもメッセージを出さないのは不親切なので、まず submit しない(サーバーに送らない)コードにする。
で、 submit の event が発生するところに JavaScript で、メッセージを表示させる。 console.log でもいいし、 alert でもいい。

で、そこで受け取ることができたら、 textarea と input の内容を確認するコードをいれる。
これも console.log とかに出力して動作確認。

で、大丈夫そうだったら submit (サーバーに送る)する。

困っているというより、プログラミングがわかりません。おしえてください。って言っているような気がして、質問ではないと思うのは私だけでしょうか?

1Like

php側でimage_indexを使おうとしていますが、htmlに該当のhidden項目がありません。
そのあとの「// $existingData がない場合(画像の変更がない場合)」以下の処理も不思議なことになっています。
おそらく既存のソースを参考にしながら書いたのかと思いますので、もう一度参考元をよく見て、1から作り直したほうが良いかもしれません。

0Like

Your answer might help someone💌