PHP MVC框架编辑时未选新图却自动变为默认图的问题
Hey there, let's tackle this issue where your industry image gets reset to the default even when you don't pick a new one. The core problem is in how your controller handles the file upload check and how the form tracks the original image value. Here's how to fix it step by step:
1. Adjust the HTML View
First, let's ensure the form properly retains the original image path and cleans up unnecessary inputs:
<form id="form-category" class="form-horizontal" action="<?php $_SERVER['PHP_SELF']; ?>" method="POST" enctype="multipart/form-data"> <div class="form-group"> <label class="col-sm-2 control-label">Image</label> <div class="col-sm-10"> <a href="" id="thumb-image" data-toggle="image" class="img-thumbnail"> <img src="<?php echo HTTP_HOST; ?>/image/<?php echo $data['industry_image']; ?>" alt="<?php echo $data['industry_name']; ?>" title="<?php echo $data['industry_name']; ?>" data-placeholder="<?php echo HTTP_HOST; ?>/image/<?php echo $data['placeholder']; ?>" width="100" height="100"> </a> <!-- Hidden input to store original image path --> <input type="hidden" name="original_industry_image" value="<?php echo $data['industry_image']; ?>"> <input type="file" class="hidden" name="industry_image" id="input-image" onchange="readURL(this);"> </div> </div> </form>
Update the Image Preview jQuery
Tweak the popover logic to ensure clearing the image explicitly sets the placeholder, and doesn't break the original image retention:
// Preview selected image function readURL(input) { if (input.files && input.files[0]) { var reader = new FileReader(); reader.onload = function (e) { $('#thumb-image').children('img').attr('src', e.target.result); } reader.readAsDataURL(input.files[0]); } } // Bootstrap image popover handler $(document).on('click', 'a[data-toggle=\'image\']', function(e) { var $element = $(this); var $popover = $element.data('bs.popover'); e.preventDefault(); // Destroy existing popovers $('a[data-toggle="image"]').popover('destroy'); if ($popover) return; $element.popover({ html: true, placement: 'right', trigger: 'manual', content: function() { return '<button type="button" id="button-image" class="btn btn-primary"><i class="fa fa-pencil"></i></button> <button type="button" id="button-clear" class="btn btn-danger"><i class="fa fa-trash-o"></i></button>'; } }).popover('show'); // Trigger file selection $('#button-image').on('click', function() { $('#input-image').trigger('click'); $element.popover('destroy'); }); // Clear image to placeholder $('#button-clear').on('click', function() { const placeholder = $element.find('img').attr('data-placeholder'); $('input[name="original_industry_image"]').val(placeholder.split('/').pop()); // Update hidden input to placeholder filename $element.find('img').attr('src', placeholder); $('#input-image').val(''); // Clear file input $element.popover('destroy'); }); });
2. Fix the Controller Logic
This is the main culprit—your original code overwrote the image with the default whenever no file was uploaded. Let's adjust it to keep the original image unless a new one is selected:
// Initialize data with original image value $originalImage = $_POST['original_industry_image'] ?? 'no-image.png'; $data = [ 'industry_name' => $_POST['industry_name'], 'industry_description' => $_POST['industry_description'], 'sort_order' => $_POST['sort_order'], 'status' => $_POST['status'], 'industry_image' => $originalImage // Default to original image ]; // Only process file upload if a file was actually selected if (!empty($_FILES['industry_image']['size'])) { $file = $_FILES['industry_image']; $fileName = $file['name']; $fileTmpName = $file['tmp_name']; $fileSize = $file['size']; $fileError = $file['error']; $fileExt = explode('.', $fileName); $fileActualExt = strtolower(end($fileExt)); $allowed = ['gif', 'jpg', 'jpeg', 'png']; $allowedFileSize = 2000000; if (in_array($fileActualExt, $allowed)) { if ($fileError === 0) { if ($fileSize < $allowedFileSize) { $fileNameNew = strtolower($data['industry_name']) . "." . $fileActualExt; $fileDestination = DIR_IMAGE . 'industries/' . $fileNameNew; $filePath = 'industries/' . $fileNameNew; // Delete old image only if it's not the placeholder if ($originalImage !== 'no-image.png' && file_exists(DIR_IMAGE . $originalImage)) { unlink(DIR_IMAGE . $originalImage); } if (move_uploaded_file($fileTmpName, $fileDestination)) { $data['industry_image'] = $filePath; } else { echo "Error: File Upload Failed. Try again."; exit; } } else { flash("file_alert alert-danger", "File size is $fileSize, maximum allowed is $allowedFileSize"); } } else { flash("file_alert alert-danger", "Error uploading the file"); } } else { $allowedExts = implode(', ', array_map(function($ext) { return "<b>$ext</b>"; }, $allowed)); flash("file_alert alert-danger", "Please upload only $allowedExts extensions"); } } // Update industry and redirect if ($this->model->editIndustry($industry_id, $data)) { redirect("catalog/industries"); } else { redirect("catalog/industries_form", $data); }
Key Controller Fixes:
- Starts with the original image value instead of defaulting to the placeholder
- Only overrides the image path if a valid new file is uploaded
- Fixes old image deletion logic to use the correct file path
- Cleans up the allowed extensions error message
3. Complete the Model's editIndustry Method
Make sure your model actually updates the industry_image field in the database—your original code was missing this critical part:
public function editIndustry($industry_id, $data) { // Update query including industry_image $this->db->query("UPDATE industry SET industry_name = :industry_name, industry_description = :industry_description, sort_order = :sort_order, status = :status, industry_image = :industry_image WHERE industry_id = :industry_id"); // Bind all values $this->db->bind(':industry_name', $data['industry_name']); $this->db->bind(':industry_description', $data['industry_description']); $this->db->bind(':sort_order', $data['sort_order']); $this->db->bind(':status', $data['status']); $this->db->bind(':industry_image', $data['industry_image']); $this->db->bind(':industry_id', $industry_id); return $this->db->execute(); }
How It Works Now:
- The edit form loads with the original image and stores its path in a hidden input
- If you submit without selecting a new image, the controller uses the original image value
- If you select a new image, it uploads it, replaces the old image (if it's not the placeholder), and updates the database
- If you click "Clear", it sets the image to the placeholder and updates the hidden input so the database gets the placeholder path
内容的提问来源于stack exchange,提问作者Leo

