Загрузка нескольких изображений в базу MySql - PullRequest
0 голосов
/ 01 августа 2020

Я пытаюсь загрузить несколько изображений продукта для веб-сайта электронной коммерции. Идея состоит в том, чтобы сохранить имя службы в таблице служб, пока изображения сохраняются в таблице service_images, но всякий раз, когда я запускаю файл php, он загружает службу в таблицу служб, но вместо этого загружает только одно изображение в таблицу service_images всех изображений. Как я могу заставить его загрузить одну службу в таблице служб, а также несколько изображений этой службы в таблице service_images?

Ниже мой код:

add-service. в c. php

<?php

if (isset($_POST['add-service'])) {

    require 'config.php';

    $shop_name = mysqli_real_escape_string($conn, $_POST['shop_name']);
    $service_cat = mysqli_real_escape_string($conn, $_POST['service_cat']);
    $service_name = mysqli_real_escape_string($conn, $_POST['service_name']);
    $service_desc = mysqli_real_escape_string($conn, $_POST['service_desc']);
    $service_price = mysqli_real_escape_string($conn, $_POST['service_price']);
    $service_type = mysqli_real_escape_string($conn, $_POST['service_type']);
    $service_images = $_FILES['service_images'];
    
    if (empty($shop_name) || empty($service_cat) || empty($service_name) || empty($service_desc) || empty($service_price) || empty($service_type)) {
        header('Location: ../services.php?error=emptyFields');
        exit();
    } elseif (!preg_match('/^[a-zA-Z0-9]*$/', $shop_name) && !preg_match('/^[a-zA-Z0-9\s]*$/', $service_name) && !preg_match('/^[a-zA-Z0-9\s \. \-]*$/', $service_desc) && !preg_match('/^[0-9\.]*$/', $service_price) && !preg_match('/^[a-zA-Z0-9\s \.]*$/', $service_type)) {
        header('Location: ../services.php?error=invalidInputs');
        exit();
    } elseif (!preg_match('/^[a-zA-Z0-9]*$/', $shop_name)) {
        header('Location: ../services.php?error=invalidShopName');
        exit();
    } elseif (!preg_match('/^[a-zA-Z0-9\s]*$/', $service_name)) {
        header('Location: ../services.php?error=invalidserviceName');
        exit();
    } elseif (!preg_match('/^[a-zA-Z0-9\s \. \-]*$/', $service_desc)) {
        header('Location: ../services.php?error=invalidDescription');
        exit();
    } elseif (!preg_match('/^[0-9\.]*$/', $service_price)) {
        header('Location: ../services.php?error=invalidPrice');
        exit();
    } elseif (!preg_match('/^[a-zA-Z0-9\s \.]*$/', $service_type)) {
        header('Location: ../services.php?error=invalidStyle');
        exit();
    } else {
        foreach ($_FILES["service_images"]["tmp_name"] as $key => $tmp_name) {
            $file_name = $_FILES["service_images"]["name"][$key];
            $file_type = $_FILES["service_images"]["type"][$key];
            $file_tempName = $_FILES["service_images"]["tmp_name"][$key];
            $file_error = $_FILES["service_images"]["error"][$key];
            $file_size = $_FILES["service_images"]["size"][$key];
    
            $a = count($_FILES['service_images']['name']);
            for ($i = 0; $i < $a; $i++) {
                $fileExt = explode('.', $file_name);
                $fileActualExt = strtolower(end($fileExt));
    
                $allowed = array('jpg', 'png', 'jpeg');
    
                if (in_array($fileActualExt, $allowed)) {
                    if ($file_error === 0) {
                        if ($file_size <= 15000000) {
    
                            $newFileName = preg_replace('/\s+/', '', $service_name) . $i . '.' . $fileActualExt;
                            echo $newFileName . "<br>";
                            $fileDestination = '../../services/' . $newFileName;

                            $sql_images = "INSERT INTO service_images (shop_name, service_name) VALUES ('$shop_name', '$service_name')";
                            $result = mysqli_query($conn, $sql_images);

                            $sql = "INSERT INTO services (shop_name, service_cat, service_name, service_desc, service_price, service_type) VALUES (?,?,?,?,?,?)";
                            $stmt = mysqli_stmt_init($conn);
                            if (!mysqli_stmt_prepare($stmt, $sql)) {
                                header("Location: ../services.php?error=SaveError");
                                exit();
                            } else {
                                mysqli_stmt_bind_param($stmt, 'ssssss', $shop_name, $service_cat, $service_name, $service_desc, $service_price, $service_type);
                                mysqli_stmt_execute($stmt);

                            // move_uploaded_file($file_tempName = $_FILES["service_images"]["tmp_name"][$i], $fileDestination);
                                header("Location: ../services.php?success");
                                exit();
                            }
    
                        } else {
                            header('Location: ../services.php?error=invalidSize');
                            exit();
                        }
                    } else {
                        header('Location: ../services.php?error=invalidImage');
                        exit();
                    }
                } else {
                    header('Location: ../services.php?error=invalidImageType');
                    exit();
                }
            }
        }
    }

}

форма

<form action="../admin/includes/add-service.inc.php" method="post" enctype="multipart/form-data">
   <input type="text" name="shop_name" id="shopName" class="form-input" placeholder="Shop Name">
   <select name="service_cat" id="serviceCat" class="form-input">
      <option> -- select category -- </option>
      <?php
         $sql = "SELECT * FROM service_category";
         $result = mysqli_query($conn, $sql);
         if (mysqli_num_rows($result) > 0) {
            while ($row = mysqli_fetch_assoc($result)) {
     ?>
            <option value="<?php echo $row['service_cat'] ?>"><?php echo $row['service_cat'] ?></option>
     <?php
           }
         }
     ?>
   </select>
   <input type="text" name="service_name" id="serviceName" class="form-input" placeholder="Service Name">
   <textarea name="service_desc" id="service_desc" cols="1" rows="5" placeholder="Description" class="form-input"></textarea>
   <input type="text" name="service_price" id="servicePrice" class="form-input" placeholder="Service Price">
   <input type="text" name="service_type" id="serviceType" class="form-input" placeholder="Service Type">
   <hr>
   <label for="serviceImages">*Select all pictures for your service</label>
   <input type="file" name="service_images[]" id="serviceImages" class="form-input" multiple>
   <button type="submit" class="btn-add" name="add-service">Add Service</button>
</form>

1 Ответ

0 голосов
/ 01 августа 2020

Во-первых, у вас дважды будет одинаковый l oop. Сначала как foreach, а затем как for. Поскольку вам нужны ключи numeri c из этого странного типа массива $ _FILES, лучше всего использовать только для l oop. Эти двойные циклы уже настолько беспорядочные, что могут вызвать неожиданные проблемы, если, например, в одном из файлов есть проблема.

Но ваша основная проблема в том, что вы в основном проверяете только одно изображение, а затем загружаете его . Если процесс проверки или успешность пройдены, в конце отображается exit();. Убивает не только l oop, но и весь скрипт. Вы не позволяете второму изображению l oop продолжать работу, так как первое его убивает .. либо в случае успеха, либо при ошибке.

Решением было бы дождаться, пока цикл завершится sh (добавление кода после скобки циклов) и поместив туда код, связанный с успехом. Если внутри циклов обнаруживается ошибка, скрипт никогда не зайдет так далеко.

enter image description here

I have no idea, how you are actually linking the images to service, but I tried to clean up your code and make the order correct. I also did my best at explaining why and where. Hopefully, you understand the problem better from this or even better, find better options to optimise your code:

// TESTING: Lets see what is inside post values:
echo '$_POST values'; print_r($_POST); echo '
'; // TESTING: Lets see what is inside the files values: echo '$_FILES values
'; print_r($_FILES); echo '
'; // Above is for testing only.. // Probably better place to load important configs: require 'config.php'; // Since these are the conditions for uploads, then they are global: // no need for them to be inside the loop: $allowed = array('jpg', 'png', 'jpeg'); // Maximum allowed filesize: $max_allowed_file_size = 15000000; // which is 15mb // We detect the submit buttons trigger name: if (isset($_POST['add-service'])) { // Do the escape thingy: // NOTE: You should be using some mysqli class for database handling: $shop_name = mysqli_real_escape_string($conn, $_POST['shop_name']); $service_cat = mysqli_real_escape_string($conn, $_POST['service_cat']); $service_name = mysqli_real_escape_string($conn, $_POST['service_name']); $service_desc = mysqli_real_escape_string($conn, $_POST['service_desc']); $service_price = mysqli_real_escape_string($conn, $_POST['service_price']); $service_type = mysqli_real_escape_string($conn, $_POST['service_type']); $service_images = $_FILES['service_images']; // Lets deal with the errors before going forward with the rest of the script: // You don't need elseif here, because your callback is to redirect and exit anyways.. if (empty($shop_name) || empty($service_cat) || empty($service_name) || empty($service_desc) || empty($service_price) || empty($service_type)) { header('Location: ../services.php?error=emptyFields'); exit(); } if (!preg_match('/^[a-zA-Z0-9]*$/', $shop_name) && !preg_match('/^[a-zA-Z0-9\s]*$/', $service_name) && !preg_match('/^[a-zA-Z0-9\s \. \-]*$/', $service_desc) && !preg_match('/^[0-9\.]*$/', $service_price) && !preg_match('/^[a-zA-Z0-9\s \.]*$/', $service_type)) { header('Location: ../services.php?error=invalidInputs'); exit(); } if (!preg_match('/^[a-zA-Z0-9]*$/', $shop_name)) { header('Location: ../services.php?error=invalidShopName'); exit(); } if (!preg_match('/^[a-zA-Z0-9\s]*$/', $service_name)) { header('Location: ../services.php?error=invalidserviceName'); exit(); } if (!preg_match('/^[a-zA-Z0-9\s \. \-]*$/', $service_desc)) { header('Location: ../services.php?error=invalidDescription'); exit(); } if (!preg_match('/^[0-9\.]*$/', $service_price)) { header('Location: ../services.php?error=invalidPrice'); exit(); } if (!preg_match('/^[a-zA-Z0-9\s \.]*$/', $service_type)) { header('Location: ../services.php?error=invalidStyle'); exit(); } // Nothing happened above, so that means the form validation should be fine and we can go forward with the images: // So as in your script, we count the images: $a = count($_FILES['service_images']['name']); // Now we do a "numeric loop", not an array loop, which is foreach: for ($i = 0; $i < $a; $i++) { // Since we have the key as numeric now, we can do what you did before, but without the foreach loop: $file_name = $_FILES['service_images']['name'][$i]; $file_type = $_FILES['service_images']['type'][$i]; $file_tempName = $_FILES['service_images']['tmp_name'][$i]; $file_error = $_FILES['service_images']['error'][$i]; $file_size = $_FILES['service_images']['size'][$i]; // Get the file extension: // NOTE: This is not good, as you should really check the mime type of the file, not the extension. $fileActualExt = strtolower(end(explode('.', $file_name))); // TESTING: We check print out the data to make sure, that all looks fine: echo 'File with the key: ' . $i .' -- $file_name: ' . $file_name . '; $file_type: ' . $file_type . '; $file_tempName: ' . $file_tempName . '; $file_error: ' . $file_error . '; $file_size: ' . $file_size . '
'; // Instead of making the code ugly, lets deal with errors, by killing the script before // NOTE: This is not good approach, you should be using Exceptions: // https://www.php.net/manual/en/language.exceptions.php // Check if the file extension is NOT in the allowed array if (!in_array($fileActualExt, $allowed)) { // Redirect: header('Location: ../services.php?error=invalidImageType'); // Kill the script: exit('invalidImageType'); } // Check if the file had an error: if ($file_error) { // Redirect: header('Location: ../services.php?error=invalidImage'); // Kill the script: exit('invalidImage'); } // Check if the image bytes are BIGGER > then max allowed file size variable: if ($file_size > $max_allowed_file_size) { // Redirect: header('Location: ../services.php?error=invalidSize'); // Kill the script: exit(); } // At this stage, hopefully, there has not been any errors above and we can deal with file freely: // Make new file name: $newFileName = preg_replace('/\s+/', '', $service_name) . $i . '.' . $fileActualExt; // echo $newFileName . "
"; // Set the new destination: $fileDestination = '../../services/' . $newFileName; // Lets move the file already. // NOTE: Make sure that you have some bash code from server side, that deletes outdated / old temp files, so they dont take space: move_uploaded_file($file_tempName = $_FILES["service_images"]["tmp_name"][$i], $fileDestination); // Insert the image to database: // NOTE: Im not sure about your specific code, but just this is there location for that: $sql_images = "INSERT INTO service_images (shop_name, service_name) VALUES ('$shop_name', '$service_name')"; $result = mysqli_query($conn, $sql_images); // PROBLEM: This is where you originally had the success message redirect and exit. // This means, you KILL the script and there for the loop. // But you have to understand, that you have two images or more, so the loop has to continue freely, // and you can do this sort of stuff at after the loop! // // header("Location: ../services.php?success"); // exit(); } // If nothing happened above, then the image uploads went trough nicely and we can deal with success messages or adding the service itself: // I have not used mysqli stmpt before, so I have no idea what is going on in this area..: // .. but this the locatin to deal with the services as this is the parent and the children are above. $sql = "INSERT INTO services (shop_name, service_cat, service_name, service_desc, service_price, service_type) VALUES (?,?,?,?,?,?)"; $stmt = mysqli_stmt_init($conn); // I don't think you need this at all, but whatever: // Shouldnt this be above if (!mysqli_stmt_prepare($stmt, $sql)) { // Redirect: header("Location: ../services.php?error=SaveError"); // Kill the script: exit(); } // This is adding the service I assume, it has to be outside the loop, as single submit = single service. But images are multiple. mysqli_stmt_bind_param($stmt, 'ssssss', $shop_name, $service_cat, $service_name, $service_desc, $service_price, $service_type); mysqli_stmt_execute($stmt); // This is where you can have the success redirect and exit, as this is after the loop: header("Location: ../services.php?success"); exit(); }

NOTES:

  1. You should be using Исключения для обработки ошибок.
  2. Узнайте разницу между foreach и для циклов.
  3. Расширения файлов можно обмануть, вместо этого проверьте тип файла mime
  4. Массив разрешенных типов файлов внутри l oop не очень умен, так как вы будете его использовать больше чем один раз за все l oop циклов. Лучше всего оставить его в верхней части скрипта, чтобы его было легче настроить в будущем. То же самое и с переменной размера файла.
  5. Было бы гораздо разумнее определять типы файлов и размеры через javascript еще до того, как они попадут на ваш сервер. Таким образом, вы в основном сохраняете проблемы с пространством в папке временных файлов и пропускной способностью.
  6. Я не понимаю, где вы на самом деле используете $ result из mysql. Или где вы связываете изображения из таблицы service_images с фактическим сервисом.
  7. Используйте <input type="file" name="service_images[]" multiple accept=".jpg, .png, .jpeg"> ( multiple accept = ". Jpg, .png, .jpeg" ) в форме чтобы пользователь не мог выбирать другие расширения. Вы также можете использовать значение «images» для всех изображений.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...